Мы можем предположить, что sed
он доступен на любом * nix, но мы не можем быть уверены, что он поддерживает sed -n
генерацию команд mv. ( ПРИМЕЧАНИЕ:sed
это делает только GNU .)
Даже в этом случае с помощью встроенных команд bash и sed мы можем быстро создать для этого функцию оболочки.
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|\(.*\)\(-[0-9.]*\.pkg\)|\1\2|' *.pkg
before:
./Xft2-2.1.13.pkg
./jasper-1.900.1.pkg
./xorg-libXrandr-1.2.3.pkg
after:
./Xft2.pkg
./jasper.pkg
./xorg-libXrandr.pkg
Создание целевых папок:
Поскольку mv
не создает целевые папки автоматически, мы не можем использовать нашу первоначальную версию sedrename
.
Это довольно небольшое изменение, поэтому было бы неплохо добавить эту функцию:
Нам понадобится служебная функция abspath
(или абсолютный путь), поскольку в bash нет этой сборки.
abspath () { case "$1" in
/*)printf "%s\n" "$1";;
*)printf "%s\n" "$PWD/$1";;
esac; }
Получив это, мы можем создать целевую папку (и) для шаблона sed / rename, который включает новую структуру папок.
Это гарантирует, что мы знаем имена наших целевых папок. Когда мы переименовываем, нам нужно будет использовать его в имени целевого файла.
# 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
В этом скрипте применяются обычные правила шаблона sed, эти шаблоны не являются PCRE (Perl-совместимые регулярные выражения). Вы можете использовать расширенный синтаксис регулярных выражений sed, используя любой из них sed -r
или в sed -E
зависимости от вашей платформы.
См. POSIX-совместимый man re_format
для полного описания базовых и расширенных шаблонов регулярных выражений sed.