Як видалити недійсні символи з імен файлів?


47

У мене є файли з такими недійсними символами

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

Це Æте, де щось пішло не так у імені файлу.

Чи є спосіб просто видалити всі недійсні символи?

або можна trбуло якось використовувати?

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

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


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сухого запуску та побачити, що буде змінено, не змінюючи його.


Чи є спосіб змінити це, щоб зберегти іноземні символи, наприклад ü та ä, наприклад?
Старійшина Гейк

На мене працював лише другий. Все було в одному каталозі, тому я не впевнений, у чому різниця ..?
Shautieh

1
@Shautieh: -n зупиняє його насправді працювати. Я уточню відповідь.
naught101

Перейменування може бути повільним при роботі з великою кількістю файлів. Якщо ви хочете прискорити це, натисніть чек на пошук. Я не впевнений, як це зробити.
isaaclw

13

У мене було декілька японських файлів зі зламаними іменами, які були відновлені зі зламаної USB-палки, і рішення вище не працювали для мене.

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

Утиліта Detox перейменовує файли, щоб полегшити роботу. Це прибирає простори та інші подібні роздратування. Він також перекладе або очистить символи латинського-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. Якщо ви використовуєте "." вона нічого не знаходить.
isaaclw

Цікаво, чи справді це працює, здається, видалити / замінити китайські символи, наприклад 的节奏啊, але ці символи є дійсним ім'ям файлу.
林果 皞

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 (наприклад *...), тому їх також слід уникати у файлах.

Прекрасні джерела для обмеження імен файлів:


1
Це те, що я шукаю! але додайте лапки для підтримки dirs з пробілами знаходьте "$ 1" -depth -exec bash -c 'sanitize "$ 0"' {} \;
mmv-ru

1

Якщо ви хочете обробляти вбудовані нові рядки, мультибайтові символи, пробіли, провідні тире, зворотні риски та пробіли, вам знадобиться щось більш надійне, дивіться цю відповідь:
https://superuser.com/a/858671/365691

Я розміщую скрипт на code.google.com, якщо когось цікавить: rnf-bash-rename-script


Сценарій, зв'язаний тут, вирішив для мене проблему
Єремія Роза

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. Якщо вірно, воно перейменовує файл командою 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]
Змінено на:
X-Men.Days.of.Future.Past.2014.1080p


-2

для файлу в *; do mv "$ file" $ (відлуння "$ file" | sed -e 's / [^ A-Za-z0-9. -] / / g'); зробив &


2
Ви повинні пояснити, що робить ваш код, і використовувати правильне форматування. Ваш код може призвести до видалення файлів, вводячи зіткнення в імена. А запускати всю справу на задньому плані - це щось нерозумно.
kasperd
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.