Переименуйте файлы, которые будут использованы для своей выгоды, но не влияние на расширения файла

Я использую это на каталоге клиента для переименования файлов с первой буквой каждого слова, используемого для своей выгоды согласно их запросу:

rename 's/\b(\w)/\u$1/g' *

Это хорошо работает, но это также использует для своей выгоды первую букву расширения, таким образом, я использую это для фиксации этого:

rename 's/\.Txt$/.txt/' *.Txt

который работает хорошо, если большинство файлов в папке является тем же (обычно верным) расширением, но боль, если они очень смешаны.

Для обхождения той проблемы я создал маленький сценарий, который похож на это (не смейтесь!):

#!/bin/bash
rename 's/\.Txt$/.txt/' *.Txt
rename 's/\.Doc$/.doc/' *.Doc
rename 's/\.Docx$/.docx/' *.Docx
...
rename 's/\.Xlsx$/.xlsx/' *.Xlsx

Я игнорирую, 'Не может переименовать *.Txt *.txt: Никакой такой файл или каталог' ошибки, и если я нахожу расширение, которое отсутствует, я просто, не добавляет что строка к моему сценарию.

Я не думаю, что это будет иметь значение, но файлы находятся на Windows Server fileshare, но я получаю доступ к нему с помощью Ubuntu 16.04LTS. Если это действительно имеет значение, то я мог скопировать их в свой локальный диск сначала, выполнить команду в Ubuntu, то положить обратно файлы при необходимости.

Там какой-либо путь состоит в том, чтобы исправить первое, переименовывают команду, чтобы проигнорировать расширения и оставить их как нижний регистр? Я могу выполнить новую команду в высокоуровневом каталоге и иметь ее, рекурсивно вызывают через все подкаталоги?

7
задан 14 November 2017 в 02:33

4 ответа

Один способ достигнуть этого мог бы состоять в том, чтобы использовать Отрицательный Lookbehind, чтобы только соответствовать границе слова - последовательность словесного символа, когда этому не предшествует литеральный период, например, дают

$ ls
alan's file.txt  bar.txt  foo

затем

$ rename -n 's/(?<!\.)\b\w*/\u$&/g' *
rename(alan's file.txt, Alan'S File.txt)
rename(bar.txt, Bar.txt)
rename(foo, Foo)

Принятие Вас также не хочет использовать для своей выгоды pluralizing s также, мы могли бы изменить это к

$ rename -n 's/(?<![.'\''])\b\w*/\u$&/g' *
rename(alan's file.txt, Alan's File.txt)
rename(bar.txt, Bar.txt)
rename(foo, Foo)

или даже

$ rename -n 's/(?<![[:punct:]])\b\w*/\u$&/g' *
rename(alan's file.txt, Alan's File.txt)
rename(bar.txt, Bar.txt)
rename(foo, Foo)
7
ответ дан 23 November 2019 в 06:13

Это использует для своей выгоды первую букву каждого слова кроме заключительного расширения:

rename -n 's/\b(.+?)\b/\u$1/g; s/(.+)\.(.)/$1\.\l$2/' *

Я протестировал с этими файлами:

$ ls -1
'a file with a '$'\n''new line.foo'
'a file with spaces.txt'
justonelongfilename.ext
no-extensions-here
this.has.many.extensions.pdf

И это переименует их как:

$ rename -n 's/\b(.+?)\b/\u$1/g; s/(.+)\.(.)/$1\.\l$2/' *
a file with a 
new line.foo -> A File With A 
New Line.foo
a file with spaces.txt -> A File With Spaces.txt
justonelongfilename.ext -> Justonelongfilename.ext
no-extensions-here -> No-Extensions-Here
this.has.many.extensions.pdf -> This.Has.Many.Extensions.pdf

Прием должен сначала использовать для своей выгоды каждую первую букву, игнорируя расширения, и затем возвратиться и сделать дополнительный нижний регистр:

  • s/\b(.+?)\b/\u$1/g; : .+? нежадный шаблон, что означает, что он найдет самое короткое соответствие. Так как это привязывается границами слова (\b), это найдет все слова (все из-за финала g). Они затем заменяются капитализированным (первая использованная для своей выгоды буква) версия себя (\l$1).

  • s/(.+)\.(.)/$1\.\l$2/ : .+ является жадным, таким образом, это найдет самое долгое соответствие. Это означает самую длинную строку до финала ., после которого будет расширение (если таковые имеются). Мы заменяем соответствие всем перед расширением ($1), a . и расширение с первой буквой понижается в корпусе снова (\l$2).


Рекурсия достаточно легка также. Если Ваша оболочка является ударом (если Вы не знаете, это, вероятно), можно использовать globstar опцию, которая делает ** соответствие 0 или больше подкаталогов:

shopt -s globstar

Теперь, выполните переименовать команду как это (это будет также работать над любыми файлами в Вашем текущем каталоге):

rename -n 's/\b(.+?)\b/\u$1/g; s/(.*)\.(.)/$1\.\l$2/' **

Для ограничения его только файлами или каталогами с расширениями использовать **/*.* вместо **.

С другой стороны, используйте find:

find /path/to/dir -exec rename -n 's/\b(.+?)\b/\u$1/g; s/(.*)\.(.)/$1\.\l$2/' {} +

И, для ограничения теми файлами и каталогами с расширением:

find /path/to/dir -name '*.*' -exec rename -n 's/\b(.+?)\b/\u$1/g; s/(.*)\.(.)/$1\.\l$2/' {} +

Обратите внимание, что все эти решения бодро переименуют каталоги, а также файлы. Если Вы не хотите это, осторожны, где Вы говорите этому рекурсивно вызывать или давать ему более определенный шаблон как *.txt.


Во всех примерах удалите-n, чтобы заставить их на самом деле сделать что-то. -n причины rename просто распечатать то, что это сделало бы и не на самом деле сделало бы что-либо. Полезный для тестирования.

5
ответ дан 23 November 2019 в 06:13

Самый разумный путь состоял бы в том, чтобы заняться всеми "словами" (с использованием границы слова \b и обращение через $1 к любому первому символу) включая расширение, но затем нижний регистр само расширение:

$ prename -nv 's/\b(.)/\u$1/g;s/^(.*)\.(.*)/$1.\l$2/' *                                                                                                                
another filename trispaced.txt renamed as Another Filename Trispaced.txt
filename_with_underschore.txt renamed as Filename_with_underschore.txt
one filename.txt renamed as One Filename.txt

Обратите внимание, что это не работает на имя файла с символами нижнего подчеркивания, т.е. границы "слова" рассматривают в пробелах (вкладки, пробелы, новые строки - который, надо надеяться, не должен быть в имени файла так или иначе).

Отметьте использование prename для мобильности к ksh, где rename на самом деле встроенная команда, не автономное perl исполняемый файл.

4
ответ дан 23 November 2019 в 06:13

Просто используйте rename 's/\b(\w)/\u$1/' * БЕЗ флага g.
Флаг g означает "глобальный =, делают это многократно". Вы делаете в 1-й раз в имени файла, и Вы не хотите делать верхний регистр в 2-й раз правом?

1
ответ дан 23 November 2019 в 06:13

Другие вопросы по тегам:

Похожие вопросы: