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

Пакетное переименование файлов, заканчивающихся точкой

У меня есть большой файловый сервер unix с одним большим ресурсом SMB. Он обслуживает клиентов Mac, Linux и Windows. Большая часть файлов в этом ящике была перенесена туда с Mac Xserve. Один из способов резервного копирования общего ресурса - через ящик Windows. Это конкретное программное обеспечение резервного копирования не работает, если в именах файлов есть символы, которые ему не нравятся.

Мне удалось исправить большинство проблем с именами файлов, но я борюсь с файлами, которые заканчиваются точкой. Например:

Я пытаюсь найти способ пакетного переименования всех файлов, заканчивающихся точкой, на одно и то же имя без точки. Так filename. становится filename

find . -name "*."

работает, чтобы найти файлы. Я пробовал пропустить его через sed:

find . -name "*." | sed 's/.$//'

который выполняет свою работу в консоли, но не переименовывает файлы. Это та часть, с которой я борюсь.

Если у вас есть версия сценария Perl rename (называется либо rename или prename):

rename 's/\.$//' *.

или версия util-linux (называемая либо rename или rename-ul):

 rename . '' *.

Если вы запустите команду без аргументов и получите что-то похожее на:

Использование: переименовать [-v] [-n] [-f] perlexpr [имена файлов]

тогда это версия сценария Perl.

Что-то вроде:

rename.ul: недостаточно аргументов

Использование: rename.ul [параметры] файл замены выражения ...

Параметры: -v, --verbose, объясните, что делается -V, --version
вывести информацию о версии и выйти -h, --help отобразить эту справку и выйти

означает, что это версия util-linux.

Вроде хакерский, но должен работать:

Если вы хотите переименовать оба файла и каталоги с конечными точками:

    find . -name "*." -print0 | xargs -0 -n 1 my_rename.sh

ИЛИ, если вы хотите переименовать только файлы:

    find . -name "*." -type f -print0 | xargs -0 -n 1 my_rename.sh

куда my_rename.sh сценарий просто:

#!/bin/bash
mv "$1" "${1%%.}"

(Также не забудьте сделать скрипт исполняемым: chmod +x my_rename.sh) 2

Похоже, он должен работать:

find . -type f -name '*\.' -exec bash -c 'mv "$1" "${$1%.}"' _ {} \;

Это ограничивает поиск только файлами с точкой в ​​конце (в противном случае он соответствует текущему рабочему каталогу, '.'), А затем выполняет цитируемый фрагмент оболочки (mv "$1" "${$1%.}") для каждого найденного файла. Во фрагменте оболочки он использует расширение и замену параметра bash для удаления завершающего символа '.'. Другой шум строки в конце необходим для find -exec: {} текст найденного совпадения, \; требуется для завершения строки exec, и я считаю, что _ сообщает exec передать {} в качестве параметра ($1) к sh команда. Честно говоря, это конкретное использование -exec для меня в новинку, я нашел его Вот.

Бит подстановки bash довольно прост, и я довольно часто использую его для переименования файлов, например FILENAME=foo.JPG; mv ${FILENAME} ${FILENAME%.JPG}.jpg удалит '.JPG' из ИМЯ ФАЙЛА и заменит его на '.jpg'

Если вы все еще хотите использовать sed, а не расширение bash, похоже, это сработает:

find . -type f -name '*\.' -exec sh -c 'mv "{}" "$(echo {} | sed s/\.$// )"' \;

Сначала я попытался решить эту проблему, не вызывая -exec вызывать sh -c, но ему не понравилось раскрытие {} при попытке выполнить sed (или в предыдущем примере подстановки bash).

Также обратите внимание, что вы должны поставить "" вокруг расширяемых имен файлов (например, {} или $ 1, в зависимости от примера), так как в ваших файлах примеров есть пробелы. Это может по-прежнему не работать в зависимости от того, какие специальные символы находятся в вашем файле (например, "в имени файла" вызовет проблемы).