Na * nix bez perla rename
dostępne
W niektórych * nix zmiana nazwy nie jest dostępna, więc należy zmienić nazwę za pomocą innej metody. Kilka lat temu zasugerowałem zmv
tutaj, która, choć świetna, niekoniecznie jest dostępna.
Używając wbudowanych i sed, możemy szybko zrobić skrypt powłoki, aby to zrobić, co daje nam bardzo podobną składnię do skryptu zmiany nazwy perla, a mimo braku pewności obsługi błędów, wykonuje zadanie.
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
}
Stosowanie
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
Powiedzmy, że chcieliśmy również utworzyć foldery docelowe ...
Ponieważ mv
nie tworzy folderów, których nie możemy używać sedrename
tak, jak tutaj, ale jest to dość niewielka zmiana, więc myślę, że fajnie byłoby też to uwzględnić.
Potrzebujemy funkcji narzędzia abspath
(lub ścieżki bezwzględnej), abyśmy mogli wygenerować folder docelowy dla wzorca sed / rename, który zawiera nową strukturę folderów.
abspath () { case "$1" in
/*)printf "%s\n" "$1";;
*)printf "%s\n" "$PWD/$1";;
esac; }
Zapewni to, że znamy nazwy naszych folderów docelowych. Kiedy zmieniamy nazwę, będziemy musieli użyć jej w nazwie pliku docelowego.
# 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"
Oto skrypt obsługujący pełny folder ...
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
}
Oczywiście nadal działa, gdy nie mamy również określonych folderów docelowych.
Jeśli chcielibyśmy umieścić wszystkie utwory w folderze, ./Beethoven/
możemy to zrobić:
Stosowanie
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
Runda bonusowa ...
Za pomocą tego skryptu przenieś pliki z folderów do jednego folderu:
Zakładając, że chcemy zebrać wszystkie dopasowane pliki i umieścić je w bieżącym folderze, możemy to zrobić:
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
Uwaga na wzorce wyrażeń regularnych sed
W tym skrypcie obowiązują reguły regularnych wzorców sed, wzorce te nie są PCRE (wyrażenia regularne zgodne z Perl). Możesz mieć rozszerzoną składnię wyrażeń regularnych, używając jednej sed -r
lub w sed -E
zależności od platformy.
Zobacz zgodny z POSIX man re_format
pełny opis podstawowych i rozszerzonych wzorców wyrażeń regularnych sed.