У меня есть большой файловый сервер unix с одним большим ресурсом SMB. Он обслуживает клиентов Mac, Linux и Windows. Большая часть файлов в этом ящике была перенесена туда с Mac Xserve. Один из способов резервного копирования общего ресурса - через ящик Windows. Это конкретное программное обеспечение резервного копирования не работает, если в именах файлов есть символы, которые ему не нравятся.
Мне удалось исправить большинство проблем с именами файлов, но я борюсь с файлами, которые заканчиваются точкой. Например:
filename.
newfile.txt.
stupid old file.
Я пытаюсь найти способ пакетного переименования всех файлов, заканчивающихся точкой, на одно и то же имя без точки. Так 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, в зависимости от примера), так как в ваших файлах примеров есть пробелы. Это может по-прежнему не работать в зависимости от того, какие специальные символы находятся в вашем файле (например, "в имени файла" вызовет проблемы).