Пакетное переименование файлов, которые заканчиваются точкой
У меня большой файловый сервер Unix, с одним большим общим ресурсом SMB. Он обслуживает клиенты Mac, Linux и Windows. Большая часть файлов в этом окне была перенесена туда с Mac Xserve. Одним из способов резервного копирования общего ресурса является окно Windows. Это конкретное программное обеспечение резервного копирования дает сбой, если в именах файлов есть символы, которые ему не нравятся.
Мне удалось исправить большинство проблем с именами файлов, но я борюсь с файлами, которые заканчиваются точкой. Например:
filename.
newfile.txt.
stupid old file.
Я пытаюсь найти способ пакетного переименования всех файлов, которые заканчиваются на точку с тем же именем без точки. Так filename.
становится filename
find . -name "*."
работает, чтобы найти файлы. Я попытался передать его через sed:
find . -name "*." | sed 's/.$//'
который выполняет работу в консоли, но фактически не переименовывает файлы. Это та часть, с которой я борюсь.
3 ответа
Если у вас есть версия сценария 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 . -type f -name '*\.' -exec bash -c 'mv "$1" "${$1%.}"' _ {} \;
Это ограничивает поиск только файлами с точкой в конце (в противном случае он соответствует текущему рабочему каталогу, '.'), А затем выполняет приведенный фрагмент оболочки (mv "$1" "${$1%.}"
) для каждого имени файла, который он находит. Во фрагменте оболочки он использует расширение и подстановку параметров bash для удаления завершающего символа '.'. Другой шум строки в конце необходим для поиска -exec: {}
это совпадающий текст из находки, \;
требуется завершить строку exec, и я считаю, _
говорит exec передать {} в качестве параметра ($1
) к sh
команда. Если честно, это конкретное использование -exec для меня в новинку, я нашел его здесь.
Бит замещения bash довольно прост, и я часто использую его для переименования файлов, например FILENAME=foo.JPG; mv ${FILENAME} ${FILENAME%.JPG}.jpg
удалит ".JPG" из FILENAME и заменит его на ".jpg"
Если вы все еще хотите использовать sed, а не bash, это выглядит так, как будто это сделает эту работу:
find . -type f -name '*\.' -exec sh -c 'mv "{}" "$(echo {} | sed s/\.$// )"' \;
Я сначала попытался решить эту проблему, не вызывая -exec
вызывать sh -c
, но это не понравилось расширению {} при попытке сделать sed (или с примером замены bash ранее).
Также обратите внимание, что вы должны поставить " " вокруг имен файлов, которые вы расширяете (например, {} или $1, в зависимости от примера), так как в ваших образцах файлов есть пробелы. Это может все еще сломаться в зависимости от того, какие специальные символы находятся в вашем файле (например, "в имени файла вызовет проблемы).
Вроде хак, но должно работать
Если вы хотите переименовать оба файла и каталоги с конечными точками:
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