Назад | Перейти на главную страницу

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

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

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

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

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

или мог tr использоваться как-нибудь?

echo "009_-_�%86ndringshåndtering.html" | tr ???

Один из способов - использовать sed:

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

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

Я предполагаю, что вы используете 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

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

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

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

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

detox -r -v /path/to/your/files
-r Recurse into subdirectories
-v Be verbose about which files are being renamed 
-n Can be used for a dry run (only show what would be changed)

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

Вот как бы я это сделал

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

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

Следуя ответам на 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 сделать пробный прогон и посмотреть, что будет изменено, не меняя этого.

Этот сценарий оболочки рекурсивно очищает каталог, чтобы файлы переносились между 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 (например, *...), поэтому их также следует избегать в именах файлов.

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

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

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, чтобы удалить точку в конце каталога.

Люди Икс: Дни минувшего будущего (2014) [1080p]
Изменено на:
Люди Икс. Дни будущего. Прошлое, 2014. 1080p

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

Я разместил скрипт на code.google.com, если кому-то интересно: r-n-f-bash-переименовать сценарий

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