Nous pouvons supposer qu'il sed
est disponible sur n'importe quel * nix, mais nous ne pouvons pas être sûrs qu'il prendra en charge la sed -n
génération de commandes mv. ( REMARQUE: seul GNU le sed
fait.)
Même ainsi, bash builtins et sed, nous pouvons rapidement créer une fonction shell pour ce faire.
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|\(.*\)\(-[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
Création de dossiers cibles:
Puisque mv
ne crée pas automatiquement les dossiers cibles, nous ne pouvons pas utiliser notre version initiale desedrename
.
C'est un changement assez petit, donc ce serait bien d'inclure cette fonctionnalité:
Nous aurons besoin d'une fonction utilitaire abspath
(ou d'un chemin absolu) car bash n'a pas cette construction.
abspath () { case "$1" in
/*)printf "%s\n" "$1";;
*)printf "%s\n" "$PWD/$1";;
esac; }
Une fois que nous avons cela, nous pouvons générer le (s) dossier (s) cible (s) pour un modèle sed / rename qui inclut une nouvelle structure de dossier.
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 prenant en charge les dossiers ...
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 non plus 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 de regex sed
Les règles de modèle sed régulières s'appliquent dans ce script, ces modèles ne sont pas PCRE (Perl Compatible Regular Expressions). Vous pourriez avoir sed étendu la syntaxe des expressions régulières, en utilisant soit sed -r
oused -E
fonction de votre plate-forme.
Voir la compatibilité POSIX man re_format
pour une description complète des modèles d'expression régulière sed basiques et étendus.