Как массово переименовать файлы с неправильной кодировкой или массово заменить недопустимые закодированные символы?

У меня есть сервер Debian, и я размещаю музыку для интернет-радиостанции. У меня проблемы с именами файлов и путями, потому что многие файлы имеют неправильную кодировку, например:

./music/Bändname - Some Title - additional Info/B�ndname - 07 - This Title Is Cörtain, The EncÃding Not.mp3

В идеале хотелось бы удалить все что не есть буквы A-Z/a-z или цифры 0-9 или тире -/нижнее подчеркивание _... Результат должен выглядеть примерно так:

./music/Bndname-SomeTitle-additionalInfo/Bndname-07-ThisTitleIsCrtain,TheEncdingNot.mp3

Как добиться этого для большого количества файлов и каталогов?

Я видел такой же вопрос: массовое переименование (или правильное отображение) файлов со специальными символами

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

3 ответа

Решение

Вы столкнетесь с некоторыми проблемами, если хотите переименовать файлы и каталоги одновременно. Переименовать только файл достаточно просто. Но вы хотите убедиться, что каталоги также переименованы. Вы не можете просто mv Motörhead/Encöding Motorhead/Encoding поскольку Motorhead не будет существовать во время вызова.

Итак, нам нужно сначала просмотреть все файлы и папки, а затем переименовать только текущий файл или папку. Следующие работы с GNU find и Bash 4.2.42 на моей OS X.

#!/usr/bin/env bash
find "$1" -depth -print0 | while IFS= read -r -d '' file; do
  d="$( dirname "$file" )"
  f="$( basename "$file" )"
  new="${f//[^a-zA-Z0-9\/\._\-]/}"
  if [ "$f" != "$new" ]      # if equal, name is already clean, so leave alone
  then
    if [ -e "$d/$new" ]
    then
      echo "Notice: \"$new\" and \"$f\" both exist in "$d":"
      ls -ld "$d/$new" "$d/$f"
    else
      echo mv "$file" "$d/$new"      # remove "echo" to actually rename things
    fi
  fi
done

Вы можете изменить регулярное выражение, используя new="${f//[\\\/\:\*\?\"<>|]/}" если вы хотите заменить что-то, что Windows не может обработать.

Сохранить этот скрипт как rename.sh, сделайте его исполняемым с chmod +x rename.sh, Затем назовите это как rename.sh /some/path,

Обязательно разрешите любые конфликты имен файлов ("NoticeАнонсы).

Если вы абсолютно уверены, что он делает правильные замены, удалите echo из сценария, чтобы фактически переименовать вещи вместо того, чтобы просто печатать, что они делают.

Чтобы быть в безопасности, я бы рекомендовал сначала проверить это на небольшом подмножестве файлов.


Варианты объяснены

Чтобы объяснить, что здесь происходит:

  • -depth обеспечит повторный поиск каталогов по глубине, чтобы мы могли "свернуть" все с самого конца. Обычно, find проходит по-разному (но не в ширину).
  • -print0 обеспечивает find вывод имеет нулевой разделитель, поэтому мы можем прочитать его с read -d '' в file переменная. Это помогает нам справляться со всевозможными странными именами файлов, включая пробелы и даже переводы строк.
  • Мы получим каталог файла с dirname, Не забывайте всегда правильно указывать свои переменные в кавычках, иначе любой путь с пробелами или символами с пробелами сломает этот скрипт.
  • Мы получим фактическое имя файла (или имя каталога) с basename,
  • Затем мы удаляем любой недопустимый символ из $f используя возможности замены строк в Bash. Неверный означает все, что не является буквой в нижнем или верхнем регистре, цифрой, косой чертой (\/), точка (\.), подчеркивание или минус-дефис.
  • Если $f уже очищено (очищенное имя идентично текущему имени), пропустите его.
  • Если $new уже существует в каталоге $d (например, у вас есть файлы с именем resume а также résumé в том же каталоге), выдайте предупреждение. Вы не хотите его переименовывать, потому что в некоторых системах mv foo foo вызывает проблему. Иначе,
  • Наконец мы переименовываем исходный файл (или каталог) в новое имя

Поскольку это будет действовать только на самой глубокой иерархии, переименование Motörhead/Encöding в Motorhead/Encoding делается в два этапа:

  1. mv Motörhead/Encöding Motörhead/Encoding
  2. mv Motörhead Motorhead

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


Примеры файлов и тестовый прогон

Давайте предположим, что некоторые файлы в базовой папке test:

test
test/Motörhead
test/Motörhead/anöther_file.mp3
test/Motörhead/Encöding
test/Randöm
test/Täst
test/Täst/Töst
test/with space
test/with-hyphen.txt
test/work
test/work/resume
test/work/résumé
test/work/schedule

Вот результат запуска в режиме отладки (с echo напротив mv), то есть команды, которые будут вызваны, и предупреждения о столкновении:

mv test/Motörhead/anöther_file.mp3 test/Motörhead/another_file.mp3
mv test/Motörhead/Encöding test/Motörhead/Encoding
mv test/Motörhead test/Motorhead
mv test/Randöm test/Random
mv test/Täst/Töst test/Täst/Tost
mv test/Täst test/Tast
mv test/with space test/withspace
Notice: "resume" and "résumé" both exist in test/work:
-rw-r—r--  …  …  test/work/resume
-rw-r—r--  …  …  test/work/résumé

Обратите внимание на отсутствие сообщений для with-hyphen.txt, schedule, а также test сам.

Я знаю, что это не совсем то, что вы хотели, но если вы знаете оригинальную кодировку, возможно, вы можете использовать convmv изменить кодировку на UTF-8, что должно исправить большинство проблем.

Это сработало для меня в папке с некоторыми неправильно закодированными польскими именами файлов:

convmv -f cp1250 -t utf8 -r .

Обратите внимание, что эта команда на самом деле ничего не переименовывает; добавлять --notest Возможность действительно переименовать файлы.

Я знаю, вы спрашивали о переименовании.

Но вы можете легко избежать этой проблемы, используя программное обеспечение, такое как MusicBrainz Picard.

Он способен идентифицировать музыку (аудио-отпечатки пальцев), загружать все необходимые данные (включая изображения обложек, если таковые имеются) из огромной базы данных MusicBrainz и перемещать файлы так, чтобы ваша коллекция могла соответствовать любому шаблону, который вам нравится. Я использую его годами, и он всегда отлично работал с чем угодно, от кириллицы до арабского языка; и, конечно, (по крайней мере, для латинских сценариев) он также может выполнять преобразование в ASCII.

При таком подходе не имеет значения, насколько грязно / плохо названа ваша коллекция на самом деле, если файлы читаемы и полны.

(Я упоминал, что это бесплатно? Как в свободе слова, так и в свободном пиве? И программное обеспечение, и база данных...?)

Другие вопросы по тегам