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


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.