Найдите и переименуйте несколько файлов, используя скрипт bash в Linux - PullRequest
1 голос
/ 04 мая 2020

Например, в каталоге /home/hel/files/ находятся тысячи файлов и сотни каталогов. Приложение сохраняет там свои выходные файлы со специальными символами в именах файлов. Я хочу заменить эти специальные символы подчеркиваниями во всех именах файлов. Например, -:"<>@

Я написал сценарий bash, который просто повторяет команду для переименования файлов с использованием Linux / Unix 'rename'.

Пример: имя файла: rename.sh

#!/bin/bash
rename "s/\'/_/g" *
rename 's/[-:"<>@\,&\s\(\)\[\]?!–~%„“;│\´\’\+#]/_/g' *
rename 'y/A-Z/a-z/' *
rename 's/\.(?=[^.]*\.)/_/g' *
rename 's/[_]{2,}/_/g' *

Я выполняю следующую команду поиска:

find /home/hel/files/ -maxdepth 1 -type f -execdir /home/hel/scripts/rename.sh {} \+

Теперь проблема:

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

Команда поиска ищет только файлы, а не каталоги.

Я пробовал другие варианты поиска, такие как:

find /home/hel/files/ -maxdepth 1 -type f -execdir sh /home/hel/scripts/rename.sh {} \+
find /home/hel/files/ -maxdepth 1 -type f -execdir sh /home/hel/scripts/rename.sh {} +
find /home/hel/files/ -maxdepth 1 -type f -execdir sh /home/hel/scripts/rename.sh {} \;

Все они работают, но с одинаковым результатом.

Что не работает:

find /home/hel/files/ -maxdepth 1 -type f -exec sh /home/hel/scripts/rename.sh {} \+

Это опасно, потому что оно переименовывает каталоги и файлы в текущем каталоге, где вы тоже вызовите команду find.

Может быть, у вас есть идея, почему это происходит или есть лучшее решение.

1 Ответ

0 голосов
/ 04 мая 2020

Сценарий rename.sh вообще не использовал свои аргументы командной строки, а вместо этого выполнял поиск файлов и каталогов (!) Самостоятельно, используя глобус *.

Измените сценарий на следующий.

#!/bin/bash
rename -d s/\''/_/g;
s/[-:"<>@\,&\s\(\)\[\]?!–~%„“;│\´\’\+#]/_/g;
y/A-Z/a-z/;
s/\.(?=[^.]*\.)/_/g;
s/[_]{2,}/_/g' "$@"

Затем используйте find ... -maxdepth 1 -type f -exec sh .../rename.sh {} +.

Изменения

  • Используйте "$@" вместо * для обработки файлов, заданных в качестве аргументов, а не все в текущем каталоге.
  • Выполнить rename только один раз, поскольку 2-й rename не найдет файлы, указанные с "$@" после того, как они были переименованы 1-м rename.
  • Используйте параметр -d, чтобы изменялись только базовые имена. find всегда ставит путь перед файлами, по крайней мере ./. Без этой опции rename изменит ./filename на mangledPath/newFilename и, следовательно, переместит файл в другой каталог.

Обратите внимание, что man rename немного вводит в заблуждение

--path, --fullpath
        Rename full path: including any directory component.  DEFAULT

-d, --filename, --nopath, --nofullpath
        Do not rename directory: only rename filename component of path.

Для данного пути rename -d 's...' some/path/basename просто обрабатывает basename и игнорирует ведущие компоненты some/path/. Если basename является каталогом, он все равно будет переименован, несмотря на параметр -d.

...