Как переименовать несколько файлов с помощью find

Я скопирую мой ТАК ответ здесь:

В Ubuntu удерживаются файлы мусора ~/.local/share/Trash/files

Существует интерфейс командной строки мусора, который можно использовать. Для установки сделайте:

sudo apt-get install trash-cli

Затем для повреждения чего-то, сделайте:

trash-put myfile.txt

39
22.09.2015, 07:56
5 ответов

Следующее прямое исправление вашего подхода:

find . -type f -name 'file*' -exec sh -c 'x="{}"; mv "$x" "${x}_renamed"' \;

Однако, это очень дорого, если у вас много совпадающих файлов, потому что вы запускаете новую оболочку (которая выполняет mv) для каждого совпадения. И если у вас есть забавные символы в любом имени файла, это взорвется. Более эффективный и безопасный подход заключается в следующем:

find . -type f -name 'file*' -print0 | xargs --null -I{} mv {} {}_renamed

Он также имеет преимущество работы со странно названными файлами. Если найдет, то это можно сократить до

find . -type f -name 'file*' -exec mv {} {}_renamed \;

Версия xargs полезна, если не использовать {}, как в

find .... -print0 | xargs --null rm

Здесь rm вызывается один раз (или с большим количеством файлов несколько раз), но не для каждого файла.

Я удалил basename в рассматриваемом вами файле, потому что, вероятно, это неправильно: вы бы переместили foo/bar/file8 в file8_renamed, а не foo/bar/file8_renamed.

Редактирование (как предложено в комментариях):

  • Добавлена укороченная найти без xargs
  • Добавлена защитная наклейка
48
27.01.2020, 19:35

Попробовав первый ответ и немного поигравшись с ним, я обнаружил, что это можно сделать немного короче и проще, используя -execdir :

find . -type f -name 'file*' -execdir mv {} {}_renamed ';'

Похоже, он также должен делать именно то, что вам нужно.

17
27.01.2020, 19:35

Я хочу расширить первый ответ и отметить, что это не сработает для добавления к имени файла с момента ./ префикс пути присутствует в аргументе имени файла.

Изменяя ответ Томаса Эркера, я считаю этот подход более общим.

find . -name PATTERN -printf "%f\0" | xargs --null -I{} mv {} "prefix {} suffix"

Параметры xargs:

- null Указывает, что каждый аргумент, переданный через stdin , заканчивается нулевым символом ( \ 0 ). Таким образом, имя файла может содержать пробелы, в противном случае каждое слово будет обрабатываться как отдельный параметр для команды mv .

-I replace-str Каждое появление replace-str будет заменено аргументом, прочитанным из stdin . Таким образом, вы можете изменить его на другую строку, если вам это нужно.

4
27.01.2020, 19:35

Мне удалось сделать нечто подобное с for, findи mv.

for i in $(find. -name 'config.yml'); do mv $i $i.bak; done

Это находит все файлы config.ymlи переименовывает их вconfig.yml.bak

6
27.01.2020, 19:35

Я подумал, что было бы неплохо, если бы здесь была возможность переименовать файл, но изменить только часть его имени. Например, расширение файла.

Какой смысл менять имя файла, если можно только добавить что-то к его имени?

find. -name "*.txt" -exec  sh -c 'x={}; mv "$x" $(echo $x | sed 's/\.txt/\.bat/g')' \;
2
12.06.2021, 16:21

Теги

Похожие вопросы