Su un * nix senza perl rename
disponibile
Su alcuni * nix non è disponibile la ridenominazione, quindi è necessario effettuare la ridenominazione utilizzando un altro metodo. Alcuni anni fa ho suggerito zmv
qui che, sebbene fantastico, non è necessariamente disponibile.
Usando builtin e sed, possiamo rapidamente creare uno script shell per fare ciò che ci dà una sintassi molto simile allo script perl rename, mentre manca un po 'di errore nella gestione della gentilezza, fa il lavoro.
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
}
uso
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
Supponiamo di voler creare anche cartelle di destinazione ...
Dal momento mv
che non crea cartelle che non possiamo usare sedrename
come è qui, ma è una modifica abbastanza piccola, quindi immagino che sarebbe bello includerlo anche.
Abbiamo bisogno di una funzione di utilità abspath
(o percorso assoluto) in modo da poter generare le cartelle di destinazione per un modello sed / rename che includa la nuova struttura di cartelle.
abspath () { case "$1" in
/*)printf "%s\n" "$1";;
*)printf "%s\n" "$PWD/$1";;
esac; }
Questo ci assicurerà di conoscere i nomi delle nostre cartelle di destinazione. Quando rinomineremo dovremo usarlo sul nome del file di destinazione.
# 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"
Ecco lo script completo per le cartelle ...
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
}
Ovviamente, funziona ancora anche quando non abbiamo cartelle di destinazione specifiche.
Se volessimo mettere tutte le canzoni in una cartella, ./Beethoven/
possiamo farlo:
uso
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
Round bonus ...
Utilizzando questo script per spostare i file dalle cartelle in una singola cartella:
Supponendo che volessimo raccogliere tutti i file corrispondenti e posizionarli nella cartella corrente, possiamo farlo:
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
Nota sui modelli di sedge regex
In questo script si applicano le normali regole del modello sed, questi modelli non sono PCRE (espressioni regolari compatibili Perl). Potresti avere esteso la sintassi delle espressioni regolari, usando una sed -r
o in sed -E
base alla tua piattaforma.
Vedere la norma POSIX man re_format
per una descrizione completa dei modelli regexp di base ed estesi sed.