На * NIX без Perl renameдоступны
В некоторых * nix переименование недоступно, поэтому необходимо выполнить переименование другим способом. Несколько лет назад я предложил zmvздесь, что, хотя и здорово, но не обязательно доступно.
Используя встроенные функции и sed, мы можем быстро создать сценарий оболочки, чтобы сделать это, что дает нам синтаксис, очень похожий на сценарий perl-переименования, и, хотя ему не хватает изощренности в обработке ошибок, он выполняет свою работу.
sedrename() {
if [ $# -gt 1 ]; then
sed_pattern=$1
shift
for file in $(ls $@); do
mv -v "$file" "$(sed $sed_pattern <<< $file)"
done
else
echo "usage: $0 sed_pattern files..."
fi
}
использование
sedrename 's/Beethoven\ -\ //g' *.mp3
before:
./Beethoven - Fur Elise.mp3
./Beethoven - Moonlight Sonata.mp3
./Beethoven - Ode to Joy.mp3
./Beethoven - Rage Over the Lost Penny.mp3
after:
./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3
Скажем, мы тоже хотели создать целевые папки ...
Поскольку mvпапки не создаются, мы не можем их использовать, sedrenameкак здесь, но это довольно небольшое изменение, поэтому я думаю, что было бы неплохо включить их тоже.
Нам нужна служебная функция abspath(или абсолютный путь), чтобы мы могли сгенерировать целевую папку (и) для шаблона sed / rename, который включает новую структуру папок.
abspath () { case "$1" in
/*)printf "%s\n" "$1";;
*)printf "%s\n" "$PWD/$1";;
esac; }
Это гарантирует, что мы знаем имена наших целевых папок. Когда мы переименуем, нам нужно будет использовать его в имени целевого файла.
# generate the rename target
target="$(sed $sed_pattern <<< $file)"
# Use absolute path of the rename target to make target folder structure
mkdir -p "$(dirname $(abspath $target))"
# finally move the file to the target name/folders
mv -v "$file" "$target"
Вот полный сценарий с поддержкой папок ...
sedrename() {
if [ $# -gt 1 ]; then
sed_pattern=$1
shift
for file in $(ls $@); do
target="$(sed $sed_pattern <<< $file)"
mkdir -p "$(dirname $(abspath $target))"
mv -v "$file" "$target"
done
else
echo "usage: $0 sed_pattern files..."
fi
}
Конечно, это все еще работает, когда у нас нет определенных целевых папок.
Если мы хотим поместить все песни в папку, ./Beethoven/мы можем сделать это:
использование
sedrename 's|Beethoven - |Beethoven/|g' *.mp3
before:
./Beethoven - Fur Elise.mp3
./Beethoven - Moonlight Sonata.mp3
./Beethoven - Ode to Joy.mp3
./Beethoven - Rage Over the Lost Penny.mp3
after:
./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3
Бонус раунд ...
Используя этот скрипт для перемещения файлов из папок в одну папку:
Предполагая, что мы хотим собрать все соответствующие файлы и поместить их в текущую папку, мы можем сделать это:
sedrename 's|.*/||' **/*.mp3
before:
./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3
after:
./Beethoven/ # (now empty)
./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3
Обратите внимание на шаблоны регулярных выражений
В этом сценарии применяются правила регулярных шаблонов sed, эти шаблоны не являются PCRE (регулярные выражения, совместимые с Perl). Вы могли бы использовать расширенный синтаксис регулярных выражений, используя один sed -rили в sed -E
зависимости от вашей платформы.
См. POSIX-совместимое man re_formatдля полного описания основных и расширенных шаблонов регулярных выражений.