Мы можем предположить, что sed
доступен для любого * nix, но мы не можем быть уверены,
он будет поддерживать sed -n
для генерации mv-команд. ( ПРИМЕЧАНИЕ: Только GNU sed
делает это.)
Несмотря на это, bash buildins и 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 regex
В этом сценарии применяются обычные правила шаблонов sed, эти шаблоны не
PCRE (регулярные выражения, совместимые с Perl). Вы могли бы сед
расширенный синтаксис регулярного выражения с использованием sed -r
или sed -E
в зависимости от вашей платформы.
См. POSIX-совместимое man re_format
для полного описания
Sed базовые и расширенные шаблоны регулярных выражений.