3

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

find . -name oldfile.txt -print0 | xargs -n 1 -0 -I % mv % newfile.txt

Проблема в том, что файл перемещается в каталог, в котором я запускаю команду, а не в каталог, в котором находится oldfile.txt . Я не могу показаться решением для этого, какие-нибудь идеи?

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

1 ответ1

3

Вместо того, чтобы полагаться на внешние команды, когда вы теряете информацию о текущем каталоге, вы можете использовать опцию find ' -execdir чтобы он выполнял команды в каталоге, в котором был найден файл.

find . -name oldfile.txt -execdir mv -- {} newfile.txt \;

На самом деле это более безопасная версия -exec которая предпочтительна в большинстве ситуаций. Единственным недостатком является то, что он не указан в POSIX, поэтому вы не найдете его во всех вариантах find - но, по крайней мере, в GNU find и BSD find вы можете.

Если вы хотите быть более безопасным, вы должны вызывать mv как mv -- source target чтобы файл, начинающийся с тире, не был неправильно интерпретирован как аргумент mv .


Если по какой-то причине вы не хотите использовать -execdir или выполнять другие сложные действия, или просто хотите немного узнать о Bash, вот как получить папку и переместить файл на основе этого:

find . -name oldfile.txt -exec bash -c 'mv -- "${0}" "$(dirname $0)"/newfile.txt' {} \;

Здесь {} передает полный путь к bash как $0 . Мы получаем его имя каталога с помощью подстановки команд ($(…)), а затем добавляем новое имя. И исходный аргумент, и имя каталога должны быть заключены в двойные кавычки, чтобы пробел не нарушал команду - в противном случае mv подумает, что вы пытаетесь переместить два файла с именем foo и bar когда файл фактически называется, например, foo bar .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .