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

19918
Afri

У меня есть сервер 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 

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

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

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

13

3 ответа на вопрос

14
mik01aj

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

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

convmv -f cp1250 -t utf8 -r . 

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

Для тех, кто имеет статический набор (или не имеет разнообразного набора кодировок), опция `convmv` удивительно проста и идеальна. Для OP, имеющего потенциальное множество кодировок, это могло бы быть объединено с другим ответом, так как `convmv`, кажется, знает, когда он или когда он не встречает правильный формат. Зацикливая наборы символов с помощью `convmv --list`, можно было бы правильно их кодировать. 10 лет назад 1
Под этим я подразумеваю, что если в качестве OP запускается сервер Debian, то в наши дни, безусловно, предполагается использование UTF8, и в этом случае можно сохранить исходные буквы. У меня была папка с несколькими нордическими символами, и я использовал: `convmv -t utf8 --nfc -f iso-8859-1 --notest -r .` -` --nfc` должен был соответствовать Linux перед ОС X или около того, просто набрав `convmv`, можно отказаться от (полезных) опций. 10 лет назад 1
13
slhck

Вы столкнетесь с некоторыми проблемами, если хотите переименовать файлы и каталоги одновременно. Переименовать только файл достаточно просто. Но вы хотите убедиться, что каталоги также переименованы. Вы не можете просто, 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="$" 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="$"если хотите заменить что-то, что 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само по себе.

Возможно, вы захотите добавить логику для обработки случая, когда место назначения `mv` уже существует, что может произойти (1), если у вас есть файлы, которые уже очищены (что приводит к` mv foo foo`), или (2) если у вас есть файлы с тем же именем, за исключением специальных символов (например, `mv Encöding Encoding`, где у вас уже есть файл` Encoding` в дополнение к `Encöding`). Scott 11 лет назад 1
Хорошая идея, спасибо. Какие-то конкретные предложения о том, что делать в этом случае? Конечно, добиться этого чистым и разумным способом труднее, чем кажется на первый взгляд. Если у вас есть что-то, не стесняйтесь редактировать, конечно. slhck 11 лет назад 0
Я не верю, что имеет смысл задуматься об обработке коллизий автоматически - просто идентифицируйте их пользователю и позвольте ему справиться с ними. Я отредактировал ваш ответ, как вы предложили. Scott 11 лет назад 0
+1 за использование примера с «Encöding» Слишком много для фин! :-) Marcel 10 лет назад 0
Через три года я все еще возвращаюсь сюда. так полезно! :-) Afri 8 лет назад 0
Я использовал этот скрипт, но изменил регулярное выражение на `new =" $ " `, Так что он удаляет только недопустимые символы Windows и сохраняет действительные такие как пробелы, амперсанды, запятые и т. д. Очень полезно, спасибо! Jeremiah Rose 5 лет назад 0
0
Alois Mahdal

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

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

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

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

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

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