Я использую это на каталоге клиента для переименования файлов с первой буквой каждого слова, используемого для своей выгоды согласно их запросу:
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, то положить обратно файлы при необходимости.
Там какой-либо путь состоит в том, чтобы исправить первое, переименовывают команду, чтобы проигнорировать расширения и оставить их как нижний регистр? Я могу выполнить новую команду в высокоуровневом каталоге и иметь ее, рекурсивно вызывают через все подкаталоги?
Один способ достигнуть этого мог бы состоять в том, чтобы использовать Отрицательный 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)
Это использует для своей выгоды первую букву каждого слова кроме заключительного расширения:
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
просто распечатать то, что это сделало бы и не на самом деле сделало бы что-либо. Полезный для тестирования.
Самый разумный путь состоял бы в том, чтобы заняться всеми "словами" (с использованием границы слова \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
исполняемый файл.
Просто используйте rename 's/\b(\w)/\u$1/' *
БЕЗ флага g.
Флаг g означает "глобальный =, делают это многократно". Вы делаете в 1-й раз в имени файла, и Вы не хотите делать верхний регистр в 2-й раз правом?