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

47

У меня есть файлы с недопустимыми символами, такими как эти

009_-_�%86ndringshåndtering.html

Это то, Æгде что-то пошло не так в имени файла.

Есть ли способ просто удалить все недопустимые символы?

или можно было trбы как-то использовать?

echo "009_-_�%86ndringshåndtering.html" | tr ???
Sandra
источник
5
Символы, вероятно, не являются «недействительными», иначе файловая система не сохранит их (если вы не сделали что-то действительно неприятное для FS). Вы пытались изменить свой язык (например, на UTF8) для правильного отображения имен?
Джеймс О'Горман

Ответы:

41

Один из способов был бы с помощью sed:

mv 'file' $(echo 'file' | sed -e 's/[^A-Za-z0-9._-]/_/g')

Замените fileсвоим именем файла, конечно. Это заменит все, что не является буквой, цифрой, точкой, подчеркиванием или тире подчеркиванием. Вы можете добавлять или удалять символы, чтобы оставить их так, как вам нравится, и / или заменить заменяющий символ на что-либо еще, или вообще ничего.

Джеймс Снерингер
источник
4
Я использовал:f='file'; mv 'file' ${f//[^A-Za-z0-9._-]/_}
Луи
1
Ищите лучшее решение Х. Хесса ниже ... (и мой забавный комментарий вместе с :))
Ян Сила
31

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

Я бы использовал "convmv". Это инструмент, который может конвертировать имена файлов из одной кодировки символов в другую. Для Западной Европы одна из этих норм обычно работает:

convmv -r -f windows-1252 -t UTF-8 .
convmv -r -f ISO-8859-1 -t UTF-8 .
convmv -r -f cp-850 -t UTF-8 .

Если вам нужно установить его на Linux на основе Debian, вы можете сделать это, выполнив:

sudo apt-get install convmv

Он работает для меня каждый раз и восстанавливает исходное имя файла.

Источник: LeaseWebLabs

mevdschee
источник
1
это выглядит многообещающе, но есть идеи, как определить кодировку? У меня есть каталог с именем, Save the current file in Word 97-2004 format\sco.workflowкоторый был создан на моем Mac (через Microsoft Office), и приведенные выше кодировки не имеют никакого эффекта.
Шридхар Сарнобат
Стоит отметить, что по умолчанию convmv работает в «тестовом» режиме, где он просто выполняет пробный прогон и сообщает, какие файлы он будет перемещать. Затем он скажет вам запустить его снова с --notestвозможностью фактически переименовать файлы.
Кенни Рассчарт
16

Я предполагаю, что вы имеете в виду, что вы хотите пересечь файловую систему и исправить все такие файлы?

Вот как я это сделаю

find /path/to/files -type f -print0 | \
perl -n0e '$new = $_; if($new =~ s/[^[:ascii:]]/_/g) {
  print("Renaming $_ to $new\n"); rename($_, $new);
}'

Это позволит найти все файлы с символами не ascii и заменить эти символы подчеркиванием ( _). Однако будьте осторожны, если файл с новым именем уже существует, он будет перезаписан. Сценарий может быть изменен для проверки такого случая, но я не включил его, чтобы сделать его простым.

Патрик
источник
13

Следующие ответы на https://stackoverflow.com/questions/2124010/grep-regex-to-match-non-ascii-characters , вы можете использовать:

rename 's/[^\x00-\x7F]//g' *

где *совпадает с файлами, которые вы хотите переименовать. Если вы хотите сделать это через несколько каталогов, вы можете сделать что-то вроде:

find . -exec rename 's/[^\x00-\x7F]//g' "{}" \;

Вы можете использовать аргумент -n, renameчтобы выполнить пробный прогон и посмотреть, что изменится, не меняя его.

naught101
источник
Есть ли способ изменить это, чтобы сохранить иностранные символы, такие как, например, ü и ä?
Старейшина Гик
Только второй работал на меня. Все было в одном каталоге, поэтому я не уверен, в чем разница ..?
Шаути
1
@Shautieh: -n останавливает его на самом деле работает. Я уточню ответ.
naught101
переименование может быть медленным при работе с большим количеством файлов. Если вы хотите ускорить это, нажмите кнопку проверки, чтобы найти. Я не уверен, как это сделать, хотя.
Isaaclw
13

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

Я рекомендую пакет детоксикации:

Утилита detox переименовывает файлы, чтобы с ними было легче работать. Это удаляет пробелы и другие подобные раздражения. Он также будет переводить или очищать символы Latin-1 (ISO 8859-1), закодированные в 8-битном ASCII, символы Unicode, закодированные в UTF-8, и экранированные символы CGI.

Пример использования:

detox -r -v /path/to/your/files
-r Рекурсировать в подкаталоги
-v быть многословным о том, какие файлы переименовываются 
-n Может использоваться для пробного запуска (только показать, что будет изменено)
Х. Хесс
источник
2
Это должно быть намного выше, я призываю всех взглянуть, detoxпрежде чем изобретать велосипед. Если вы посмотрите на справочную страницу, то увидите, что она охватывает все другие предлагаемые решения из-за своей гибкости.
emk2203
Иезекииль 25:17 - Блажен, кто во имя милосердия и доброй воли поддерживает это решение, потому что он действительно хранитель своего брата и искатель потерянных детей.
Ян Сила
Интуитивно, путь не может быть "." в Debian. Если вы используете «.» ничего не находит.
Исаакль
Интересно, если это действительно работает, кажется, удалить / заменить китайские символы, например 的节奏啊, но эти символы являются допустимым именем файла.
皞 皞
5

Этот сценарий оболочки рекурсивно очищает каталог, чтобы сделать файлы переносимыми между Linux / Windows и FAT / NTFS / exFAT. Он удаляет управляющие символы /:*?"<>\|и некоторые зарезервированные имена Windows, такие как COM0.

sanitize() {
  shopt -s extglob;

  filename=$(basename "$1")
  directory=$(dirname "$1")

  filename_clean=$(echo "$filename" | sed -e 's/[\\/:\*\?"<>\|\x01-\x1F\x7F]//g' -e 's/^\(nul\|prn\|con\|lpt[0-9]\|com[0-9]\|aux\)\(\.\|$\)//i' -e 's/^\.*$//' -e 's/^$/NONAME/')

  if (test "$filename" != "$filename_clean")
  then
    mv -v "$1" "$directory/$filename_clean"
  fi
}

export -f sanitize

sanitize_dir() {
  find "$1" -depth -exec bash -c 'sanitize "$0"' {} \;
}

sanitize_dir '/path/to/somewhere'

Linux менее ограничен в теории ( /и \0строго запрещен в именах файлов), но на практике несколько символов мешают командам bash (например *...), поэтому их также следует избегать в именах файлов.

Прекрасные источники для ограничений именования файлов:

KrisWebDev
источник
1
Это то, что я ищу! но добавьте кавычки для поддержки директорий с пробелами find "$ 1" -depth -exec bash -c 'sanitize "$ 0"' {} \;
mmv-ru
1

Если вы хотите работать со встроенными символами новой строки, многобайтовыми символами, пробелами, начальными чертами, обратными слешами и пробелами, вам понадобится что-то более надежное, см. Этот ответ:
https://superuser.com/a/858671/365691

Я разместил скрипт на code.google.com, если кому-то интересно: rnf-bash-rename-script

A.Danischewski
источник
Сценарий, связанный здесь, решил проблему для меня
Иеремия Роуз
0

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

for f in *.srt; do nf=$(echo "$f" |sed -e 's/[^A-Za-z0-9.-]/./g;s/\.\.\././g;s/\.\././g'); test "$f" != "$nf" && mv "$f" "$nf" && echo "$nf"; done
  1. Обрабатывать только файлы * .srt (вместо * .srt можно использовать * для обработки каждого файла)
  2. Удаляет все остальные символы, кроме букв A-Za-z, цифр 0-9, точек "." И тире "-"
  3. Удаляет возможные двойные или тройные периоды
  4. Проверяет, нужно ли изменить имя файла
  5. Если true, он переименовывает файл с помощью команды mv, а затем выводит изменения, сделанные с помощью команды echo.

Он работает для нормализации имен каталогов фильмов:

for f in */; do nf=$(echo "$f" |sed -e 's/[^A-Za-z0-9.]/./g' -e 's/\.\.\././g' -e 's/\.\././g' -e 's/\.*$//'); test "$f" != "$nf" && mv "$f" "$nf" && echo "$nf"; done

Те же шаги, что и выше, но я добавил еще одну команду sed для удаления точки в конце каталога

X-Men Days of Future Past (2014) [1080p]
Изменено на:
X-Men.Days.of.Future.Past.2014.1080p

Брайан Кюппер
источник
-2

для файла в *; do mv "$ file" $ (повторить "$ file" | sed -e 's / [^ A-Za-z0-9. -] / / g'); сделанный &

Хайро Бернал
источник
2
Вы должны объяснить, что делает ваш код, и использовать правильное форматирование. Ваш код может привести к удалению файлов путем введения в имена конфликтов. И запускать все это на заднем плане довольно глупо.
Касперд