bash и find: как изменить имя пути от нижнего уровня вверх

Вопрос или проблема

Я запускаю следующую команду, чтобы рекурсивно избавиться от символов в папках, которые создают проблемы с определенными приложениями, скриптами или на NFS/SMB, т.е. заменяю ' на , ? на (китайский символ), : на (китайский символ) и т.д.

$ find . -type d -execdir /usr/local/bin/rename "s/'/’/g" '{}' +

(rename — это perl-скрипт Аристотеля Пагалтиса)

Проблема в том, что если данный путь имеет два или более вхождений указанных символов на двух разных уровнях, не получается внести изменения во второй раз, так как исходный путь больше не существует, например, в /data/videos/john's pics/folder/last year's bday/folder/ возникает ошибка No such file or directory., потому что там два '.

Я думаю запустить вышеуказанную команду find рекурсивно снизу вверх, но не знаю, как это сделать и является ли это лучшим подходом.

Использование find или любых других утилит/скриптов nix, таких как awk и т.д., меня устраивает.

Предполагая использование GNU findutils, используйте опцию -depth у ‘find’, чтобы выводить подкаталоги перед родительской директорией.

Ответ или решение

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

1. Основная концепция

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

2. Пример команды

Ваш оригинальный запрос можно адаптировать следующим образом:

find . -depth -type d -execdir /usr/local/bin/rename 's/'\'/'’/g' '{}' +

3. Расшифровка команды

  • find . – искать начиная с текущего каталога.
  • -depth – обработка содержимого директорий перед директорией самой.
  • -type d – фильтр для обработки только директорий.
  • -execdir – выполнение команды в директории, где найден объект (в данном случае, директория).
  • /usr/local/bin/rename – утилита для изменения имен файлов.
  • 's/'\'/'’/g' – регулярное выражение для замены символа ' на . Обратите внимание на экранирование кавычек.
  • '{}' + – подстановка имени найденной директории в команду.

4. Дополнительные замены

Если вам необходимо произвести множественные замены в одном проходе, вы можете объединить выражения в одном вызове rename с использованием Perl:

find . -depth -type d -execdir /usr/local/bin/rename 's/'\'/'’/g; s/\?/\UFF1F/g; s/:/\UFF1A/g' '{}' +

В этом примере \UFF1F и \UFF1A представляют собой соответствующие китайские замены для ? и :. Вы можете адаптировать это для любых других символов, которые вам необходимо заменить.

5. Проверка результатов

После выполнения команды проверьте изменения, используя команду find для вывода списка всех директорий:

find .

Это позволит вам убедиться в корректности замен.

Заключение

Использование ключа -depth в сочетании с утилитой rename обеспечивает безопасность и надежность при внесении изменений в структуру каталогов, предотвращая ошибки, связанные с отсутствующими директориями. Этот подход является эффективным и оптимизированным решением для вашей задачи по очистке имен директорий от нежелательных символов.

Оцените материал
Добавить комментарий

Капча загружается...