Массовое переименование файлов на камкордерах, включая пробелы

Я пытаюсь переименовать пакетные имена с именами, отмеченными на верблюжьих именах, чтобы включить пробелы между соседними верхними и нижними регистрами. Я использую Mac OS, поэтому утилиты, которые я использую, являются BSD-вариантом.

Например:

250 - ErosPhiliaAgape.mp3 => 250 - Eros Philia Agape.mp3 

Я пытаюсь find соответствующие файлы и передать их в mv который запускает sed в подоболочке, используя эту команду:

 find . -name "*[az][AZ]*" -print0 | xargs -0 -I {} mv {} "$(sed -E 's/([az])([AZ])/\1 \2/g')" 

Индивидуально эти команды работают нормально: find вытаскивает правильные файлы, а sed переименовывает их правильно, но когда я их совмещаю с xargs, ничего не происходит.

Что мне нужно изменить, чтобы сделать эту работу?

3 Solutions collect form web for “Массовое переименование файлов на камкордерах, включая пробелы”

Проблема в том, что xargs $(...) в вашей команде оценивается в момент запуска этой команды и не оценивается xargs для каждого файла. Вы могли бы использовать find -exec вместо того, чтобы оценивать команды для каждого файла в sh , а также соответствующим образом заменять цитирование:

 find . -name "*[az][AZ]*" -type f -exec sh -c 'echo mv -v "{}" "$(echo "{}" | sed -E "s/([az])([AZ])/\1 \2/g")"' \; 

Если результат этого выглядит неплохо, отбросьте echo в echo mv . Обратите внимание, что из-за echo | sed echo | sed , это не будет работать с именами файлов со встроенным \n . (Но это было уже существующее ограничение в вашей собственной попытке, поэтому я надеюсь, что это приемлемо.)

Ваша команда sed принимает входные данные из трубы. Он конкурирует с xargs , поэтому каждая из двух команд получит часть данных, записанных find (каждый байт переходит только к одному читателю), и это непредсказуемо, что получает что.

Вам нужно будет связать каждое имя файла с sed , что означает, что вам нужна промежуточная оболочка для настройки канала.

 find . -name "*[az][AZ]*" -print0 | xargs -0 -I {} sh -c 'mv "$0" "$(echo "$0" | sed -E '\''s/([az])([AZ])/\1 \2/g'\'')"' {} 

Вам не нужны xargs , это в основном бесполезно. find может вызвать программу напрямую.

 find . -name "*[az][AZ]*" -exec sh -c 'mv "$0" "$(echo "$0" | sed -E '\''s/([az])([AZ])/\1 \2/g'\'')"' {} \; 

Кроме того, установите любую из реализаций rename Perl, например File::Rename или одну из Unicode::Tussle .

 cpan File::Rename find -depth . -exec rename 's!([az])([AZ])(?!.*/)!$1 $2!g' {} + 

Бит (?!.*/) Запрещает замену от запуска в именах каталогов, если они содержат видеокамеру. Передача -depth для find гарантирует, что если каталог переименован, это произойдет после find как find переместит его.

Если вы предпочитаете использовать GNU Parallel, это решение:

 find . -name "*[az][AZ]*" -type f | parallel mv -v {} '{= s:([az])([AZ])(?!.*/):$1 $2:g =}' 
  • Как передать строки с одинарными кавычками в grep?
  • копировать файлы с целевым именем на основе md5, используя find и xargs
  • Xargs для извлечения имени файла
  • Как найти и скопировать файлы на основе расширения?
  • Найти файлы рекурсивно, которые старше одного года и не принадлежат конкретному пользователю
  • 'find -mtime -1 -print | xargs tar 'архивирует все файлы из каталога, игнорируя аргумент -mtime -1
  • Обработка временных меток вывода tcpdump в режиме реального времени
  • Сортировка вывода «find»?
  • вывод искажается при параллельном запуске «xargs ls»
  • `grep -l .. | xargs vim` генерирует предупреждение, почему?
  • Добавить строку во многие файлы
  • Linux и Unix - лучшая ОС в мире.