Иногда бывает жизненно необходимо переименовать кучу файлов. Например заменить пробелы в названии файлов и директорий на нижний знак подчеркивания.
Сохраняем приведенный ниже скрипт в файл с именем mass-replace.sh
#!/bin/shСделаем файл исполняемым
# Определяем глубину вложенности директорий
depth=$((`find "$1" -type d -print | \
sed -E 's/[^\/]+//g' | \
sort | tail -n 1 | \
wc -c`+1));
# Макрос, переименовывающий файлы и директории
replacer='new="`dirname "{}"`/`basename "{}" | sed "s/ /_/g"`"; if [ "$new" != "{}" ]; then mv "{}" "$new"; fi;';
# Обходим все уровни вложенности
while [ $depth -ge 0 ];
do
# Находим и заменяем
find "$1" -depth $depth -and -name '* *' -print -exec sh -c "$replacer" \;
# Меняем уровень вложенности
depth=$(($depth-1));
done;
$ chmod +x mass-replace.shВ качестве аргумента скрипту передается путь до обрабатываемой директории
$ ./mass-replace.sh ~/Warez/Music
17 комментариев:
А перловская приблуда rename?
find ... | xargs rename 's/ /_/g'
ну попробуйте, мне тоже интересно :)
А чего пробовать? Я всегда так делаю :)
Сами вложенные директории и их файлы тоже обрабатывает?
$ find test | xargs rename 's/ /_/g'
rename: too many arguments.
rename: too many arguments.
sh -c "$replacer" — это хорошо
Я обычно для exec маленький скриптик писал, временный… Такое простое решение как-то в голову не приходило. Спасибо.
Если пачку нужных REPLACERs теперь поместить куда-нибудь в .bashrc, то пользоваться find для массовых операций над файлами будет удобнее…
Да, вы правы, вложенные директории не обрабатываюся :(
Несколько поздно, конечно, но мне ваш скрипт пригодился сегодня только. У меня вопрос такой - а зачем нужны выяснять глубину вложенности и потом идти по уровням? Ведь просто find тоже способен пройти по всем файлам?
Дело в том что скрипт переименовывает не только файлы, но и директории тоже. Если начать обрабатывать все подряд без разбору то велика вероятность, что первым будет переименована вышестоящая директория и вследствие чего дочерние директории, тоже требующие обработки, выпадут из процесса и скрипт завалит вас сообщениями об ошибках.
Поправка: ...«и вследствие чего дочерние директории и файлы»...
Понял, спасибо большое. Сам бы не догадался :(
Всё проще гораздо:
http://linuxforum.ru/index.php?s=&showtopic=73512&view=findpost&p=716305
Один find и один цикл.
С сортировкой действительно получается проще.
find -name "* *" | sort -r | while read i; do mv "$i" "$(dirname "$i")/$(basename "$i" | tr ' ' _)"; done
Да, кстати: синтаксис `...` уже давно deprecated. Рекомендуется использовать $(...). Я даже как-то на ошибку напоролся: http://forum.posix.ru/viewtopic.php?id=943
rename всё же удобнее, да и команда всего одна нужна.
Вот описание на русском с примерами.
rename НЕ умеет обрабатывать ВЛОЖЕННЫЕ директории.
Но в комбинации с find умеет )
find . -exec rename 's/ /_/g' {} \; -print
Это как альтернатива тому что предложил vti.
Отправить комментарий