Рекурсивно переименовывать файлы (изменять расширение) в Linux


22

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

find . -name "*.andnav" -exec rename .andnav .tile {} \;
syntax error at (eval 1) line 1, near "."

...

rename -nv 's/\.andnav$/\.tile/i' *.andnav
0.png.andnav renamed as 0.png.tile

1
У вас есть Debian renameили Red Hat rename?
Игнасио Васкес-Абрамс

@Ignacio: Ubuntu = Debian?
эндолит

Да, Ubuntu - это производная от Debian.
Игнасио Васкес-Абрамс

Ответы:


23

Догадаться

find . -name "*.andnav" -exec rename -v 's/\.andnav$/\.tile/i' {} \;
./0/0.png.andnav renamed as ./0/0.png.tile
./0/1.png.andnav renamed as ./0/1.png.tile
./1/0.png.andnav renamed as ./1/0.png.tile
./1/1.png.andnav renamed as ./1/1.png.tile

конечно удалите -v, когда будете это делать, иначе вы потеряете время на отображение всех файлов


14

Что-то типа:

find . -name '*.andnav' -exec sh -c 'mv "$0" "${0%.andnav}.tile"' {} \;

этот работал лучше всего для меня
cwd


4

Я обнаружил, что этот метод легче и легче читать:

find . -name "*.andnav" | rename "s/\.andnav$/.tile/"

По крайней мере, в деривациях Ubuntu переименование берет список файлов из STDIN, если их нет в командной строке. И это можно легко проверить с помощью:

find . -name "*.andnav" | rename -vn "s/\.andnav$/.tile/"

пока не поймешь правильно.


1

Переименуйте файлы и каталоги с find -execdir | rename

Если вы собираетесь переименовывать как файлы, так и каталоги не просто с помощью суффикса, тогда это хороший шаблон:

PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" \
  find . -depth -execdir rename 's/findme/replaceme/' '{}' \;

В отличие от этого, потрясающая -execdirопция делает cdв каталог перед выполнением renameкоманды -exec.

-depth убедитесь, что переименование происходит сначала для детей, а затем для родителей, чтобы предотвратить потенциальные проблемы с отсутствующими родительскими каталогами.

-execdir требуется, потому что переименование плохо работает с путями ввода неосновного имени, например, следующие ошибки:

rename 's/findme/replaceme/g' acc/acc

PATHХакерство требуется , потому что -execdirимеет один очень досадный недостаток: findкрайне самоуверенный и отказывается что - либо делать с , -execdirесли у вас есть какие - либо относительные пути в вашем PATHпеременном окружении, например ./node_modules/.bin, в противном случае с:

find: Относительный путь «./node_modules/.bin» включен в переменную среды PATH, которая небезопасна в сочетании с действием -execdir команды find. Пожалуйста, удалите эту запись из $ PATH

Смотрите также: /ubuntu/621132/why-using-the-execdir-action-is-insecure-for-directory-which-is-in-the-path/1109378#1109378

-execdirявляется расширением GNU find для POSIX . renameоснован на Perl и поставляется из renameпакета. Проверено в Ubuntu 18.10.

Переименовать обходное решение

Если ваши входные пути не приходят findили вам надоело относительное раздражение пути, мы можем использовать некоторые возможности Perl для безопасного переименования каталогов, как в:

git ls-files | sort -r | xargs rename 's/findme(?!.*\/)\/?$/replaceme/g' '{}'

Я не нашел удобный аналог для -execdirс xargs: Xargs: изменение рабочего каталога путь к файлу перед выполнением?

sort -rТребуется для того , чтобы файлы приходят после их соответствующих каталогов, так как более длинные пути приходят после того, как более короткие, с тем же префиксом.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.