Я нашел этот ответ, как я ... но он просто не работает - он не переименовал какой-либо файл для неизвестного мне причины
Прежде чем я начал искать вокруг я думал, что это должно быть легкой задачей даже для начинающего пингвина, но для меня это не кажется.
Например, я просто не могу сказать ls перечислить все *.txt в все вложенные папки, которые были для меня неожиданностью (без grep или подобных). Затем я обнаружил, что find и find . -name name_1.txt перечислены файлы в порядке, но
for f in $(find . -name name_1.txt) ; do echo "$f" ; done
разделяет целые пути файла с пространством как разделителем, поэтому непригодно передавать этот вывод некоторым команда, подобная mv или rename
Я хочу спросить, что случилось с командой выше, и, если возможно, какой-нибудь изящный oneliner, чтобы я мог рекурсивно переименовать name_1.txt в name_2.txt
команда mmv сделает это в довольно простом вызове:
mmv "; name_1.txt" "# 1name_2.txt"
";" подстановочный знак, который повторно используется в заменяемом имени файла как «# 1», также совпадает с подкаталогами.
Если вам нужны более сложные примеры, вы должны изучить man-страницу.
Как указывает @ams, многие рекурсивные решения для замены требуют, чтобы вы работали со всем путем, а не только с именем файла.
Я использую действие find -execdir для решения этой проблемы , Если вы используете -execdir вместо -exec, указанная команда запускается из подкаталога, содержащего сопоставленный файл. Таким образом, вместо передачи всего пути к rename он пропускает только ./filename. Это значительно упрощает запись команды replace.
find /the/path -type f \
-name '*_one.txt' \
-execdir rename 's/\.\/(.+)_one\.txt$/$1_two.txt/' {} \;
Подробнее:
-type f означает, что поиск файлов, а не каталогов -name '*_one.txt' означает означает только совпадение имен файлов это конец в _one.txt В этом ответе я использую команду rename вместо mv. rename использует регулярное выражение Perl для переименования каждого файла. Обратные косые черты после -type и -name являются символами продолжения строки bash. Я использую их, чтобы сделать этот пример более читабельным, но на практике они не нужны. Однако обратная косая черта в конце строки -execdir требуется. Здесь есть esacpe точка с запятой, которая завершает команду, выполняемую -execdir. Весело!Объяснение регулярного выражения:
-type f означает только поиск файлов, а не каталогов \.\/, совпадающих с ведущим ./, который -execdir проходит в Используйте \, чтобы избежать. и / metacharacters -name '*_one.txt' означает означает только совпадение имен файлов, заканчивающихся в _one.txt _one\.txt, совпадение «_one.txt», выход из метасимвола точки . В этом ответе я использую rename вместо mv. rename использует регулярное выражение Perl для переименования каждого файла. / отмечает конец части «соответствия» регулярного выражения и начало части «заменить» . Обратные косые черты после -type и -name - символ продолжения строки bash. Я использую их, чтобы сделать этот пример более читабельным, но на практике они не нужны. _two.txt имя нового файла закончится в «_two.txt». Не нужно избегать метасимвола точки здесь, в разделе «замена» Однако обратная косая черта в конце строки -execdir требуется. Здесь есть esacpe точка с запятой, которая завершает команду, выполняемую -execdir. Fun!До
tree --charset=ascii
|-- a_one.txt
|-- b_one.txt
|-- Not_this.txt
`-- dir1
`-- c_one.txt
После
tree --charset=ascii
|-- a_two.txt
|-- b_two.txt
|-- Not_this.txt
`-- dir1
`-- c_two.txt
Подсказка: rename - n. Он выполняет сухой запуск и показывает вам, какие имена он изменит, но не вносит никаких изменений.
Вы можете изучить множество доступных вариантов:
`$ apt-cache search rename | grep -i rename`