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

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

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

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

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

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

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

Спасибо!

решение1

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

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

    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, может отличаться у вас.


EDIT: Изменение mv $iкоманды на `mv -i $i' заставит mv выводить запрос перед перезаписью существующего файла.

EDIT2: Чтобы работать с именами файлов с пробелами, вы можете изменить переменную IFS (разделитель полей ввода) bash следующим образом (адаптировано изздесь):

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/\.\///

Удалить текущий каталог из вывода find, вывести «foo» вместо «./foo».

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

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


Связанный контент