Сценарий оболочки, чтобы исправить плохие имена файлов?

Я ЭТО в моей маленькой фирме; и, несмотря на мои страшные предупреждения, все помещают на сервер файлы с ужасными именами, включая пробелы в начале и в конце, плохие символы (включая \ ; / + . < > - так далее!)

Они делают это, обращаясь к серверу (FreeBSD/FreeNAS) через AFP на Mac, так что ни одна часть системы не жалуется.

Есть ли скрипт, который я могу использовать, чтобы пройти через все дерево каталогов и исправить неправильные имена файлов?

В основном заменить все пробелы и плохой ASCII с _... и если файл уже существует, просто нажмите _2 или что-то в конце.

Я не думаю, что есть способ заставить систему обеспечивать соблюдение правил именования файлов, не так ли?

Спасибо!

1 ответ

Решение

Я бы использовал Bash и найти. Я уверен, что есть более простой вариант, но вот что я придумал:

  1. Это может иметь дело с именами файлов, содержащими "/" (команда find выдаст предупреждение, проигнорирует его), но будет работать только с файлами в текущем каталоге (без подкаталогов). Я не мог понять, как сказать bash или найти разницу между "/" в имени файла и "/", который является частью пути.

    for i in $(find . -maxdepth 1 -type f  -name "*[\:\;><\@\$\#\&\(\)\?\\\/\%]*" | sed 's/\.\///'); do mv "$i" ${i//[\;><\@\$\#\&\(\)\?\\\/\%]/_}; done
    
  2. Этот не может иметь дело с именами файлов, содержащими "/", но он будет работать со всеми файлами в текущем каталоге и его подкаталогах:

    for i in $(find . -type f  -name "*[\:\;\>\<\@\$\#\&\(\)\?\\\%]*"); do mv "$i" ${i//[\;><\@\$\#\&\(\)\?\\\%]/_}; done
    

Обязательно проверьте их перед запуском. Они отлично работали в тех нескольких тестах, которые я проводил, но я не был исчерпывающим. Также имейте в виду, что я в системе Linux. Конкретная реализация find и, возможно, bash может отличаться от вашей.


РЕДАКТИРОВАТЬ: Изменение mv $i Команда `mv -i $i 'заставит mv предложить вам перезаписать существующий файл.

РЕДАКТИРОВАТЬ 2: Чтобы иметь дело с именами файлов с пробелами, вы можете изменить переменную bash IFS (Разделитель входных полей) следующим образом (адаптировано здесь):

SAVEIFS=$IFS; IFS=$(echo -en "\n\b"); for i in $(find . -type f  -name "*[\:\;\>\<\@\$\#\&\(\)\?\\\%\ ]*"); do mv "$i" ${i//[\;><\@\$\#\&\(\)\?\\\%\ ]/_}; done; IFS=$SAVEIFS

Я также изменил регулярное выражение для соответствия / замены пробелов подчеркиванием. Бит SAVEIFS просто возвращает переменную IFS в исходную конфигурацию.


ОБЪЯСНЕНИЕ:

for i in $(command); do something $i; done

Это общий цикл bash. Он будет проходить через вывод команды, последовательно устанавливая переменную $ i для каждого из значений, возвращаемых командой, и будет что-то с ней делать.


find . -maxdepth 1 -type f  -name "*[\:\;><\@\$\#\&\(\)\?\\\/\%]*" '

Найти все файлы в текущем каталоге, имя которых содержит один из следующих символов: :;><@$#&()\/%, Чтобы добавить больше, просто экранируйте их с помощью "\" (например, "\¿") и добавьте их в список в квадратных скобках ([ ]). Возможно, не все эти символы нужно экранировать, но я никогда не могу вспомнить, какие специальные переменные в какой среде, поэтому я избегаю всего, на всякий случай.

sed 's/\.\///

Удалите текущий каталог из результатов поиска, напечатайте "foo" вместо "./foo".

mv "$i" ${i//[\;><\@\$\#\&\(\)\?\\\/\%]/_}

Каждый раз, когда этот маленький цикл scipt, $i будет именем файла с плохим именем. Эта команда переместит (переименует) этот файл, изменив все ненужные символы на "_". Посмотрите замену bash для получения дополнительной информации.


Другие вопросы по тегам