Назад | Перейти на главную страницу

Рекурсивно переименовывать файлы с помощью find и sed

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

find spec -name "*_test.rb" -exec echo mv {} `echo {} | sed s/test/spec/` \;

NB: после exec появляется дополнительное эхо, так что команда печатается, а не выполняется, пока я ее тестирую.

Когда я запускаю его, вывод для каждого совпадающего имени файла:

mv original original

т.е. замена на sed была потеряна. Что за хитрость?

Слишком сложно. Если у вас есть rename доступна команда, вы можете попробовать следующее:

find . -name "*_test.rb" -print0 | xargs -0 rename "s/_test/_spec/" 

Это находит соответствующие файлы, отправляет их в xargs, который, в свою очередь, использует инструмент переименования (который переименовывает файлы в соответствии с заданным регулярным выражением Perl).

Если у вас нет rename (это действительно короткий сценарий Perl), или ваше переименование является более упрощенной версией util-linux, или вы просто хотите знать, как заставить вашу команду работать: вам просто нужно отправить ее в оболочку для выполнения:

find spec -name "*_test.rb" -exec sh -c 'echo mv "$1" "$(echo "$1" | sed s/test.rb\$/spec.rb/)"' _ {} \;

На странице руководства по переименованию util-linux:

   rename '_with_long_name' '' file_with_long_name.*

will remove the substring in the filenames.

Итак, эта команда работает, если у вас нет версии переименования Perl:

find . -name "*_test.rb" -print0 | xargs -0 rename "_test..rb" "_spec/rb"