Sur un * nix sans perl rename
disponible
Sur certains * nix, il n'y a pas de renommage disponible, il est donc nécessaire de le renommer en utilisant une autre méthode. Il y a quelques années, j'ai suggéré zmv
ici qui, bien que génial, n'est pas nécessairement disponible non plus.
En utilisant les fonctions intégrées et sed, nous pouvons rapidement créer un script shell pour ce faire, ce qui nous donne une syntaxe très similaire au script de changement de nom perl, tout en manquant de gentillesse de gestion des erreurs, il fait le travail.
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
}
Usage
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
Supposons que nous voulions également créer des dossiers cibles ...
Étant donné mv
que ne crée pas de dossiers que nous ne pouvons pas utiliser sedrename
tels qu'ils sont ici, mais c'est un assez petit changement, donc je pense que ce serait bien de l'inclure aussi.
Nous avons besoin d'une fonction utilitaire abspath
(ou d'un chemin absolu) pour pouvoir générer le ou les dossiers cibles pour un modèle sed / rename qui inclut une nouvelle structure de dossiers.
abspath () { case "$1" in
/*)printf "%s\n" "$1";;
*)printf "%s\n" "$PWD/$1";;
esac; }
Cela garantira que nous connaissons les noms de nos dossiers cibles. Lorsque nous renommerons, nous devrons l'utiliser sur le nom du fichier cible.
# 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"
Voici le script complet du dossier ...
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
}
Bien sûr, cela fonctionne toujours lorsque nous n'avons pas de dossiers cibles spécifiques.
Si nous voulions mettre toutes les chansons dans un dossier, ./Beethoven/
nous pouvons le faire:
Usage
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
Tour bonus ...
Utilisation de ce script pour déplacer des fichiers de dossiers dans un seul dossier:
En supposant que nous voulions rassembler tous les fichiers correspondants et les placer dans le dossier actuel, nous pouvons le faire:
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
Remarque sur les modèles d'expression régulière sed
Les règles de modèle sed standard s'appliquent dans ce script, ces modèles ne sont pas PCRE (Perl Compatible Regular Expressions). Vous auriez pu avoir une syntaxe d'expression régulière étendue sed, en utilisant soit sed -r
ou sed -E
selon votre plateforme.
Voir le conforme POSIX man re_format
pour une description complète des modèles regexp de base et étendus sed.