Re: Renommer récursivement
Le 18/09/2010 13:41, Nicolas Roudninski a écrit :
> Bonjour à tous,
>
> J'imagine que cette question a du être maintes fois soulevée mais j'ai
> beau googeliser, je ne trouve pas de réponse satisfaisante...
>
> Je dispose d'une grande collection de musique organisée en sous
> répertoires (Artiste/Albums/titre ou Artiste/Albums/disque-n/Titre). Or
> je voudrais remplacer dans tous les répertoires et fichiers, les espaces
> par des underscores.
> J'ai tenté : find /opt/audio -exec rename 's/\s+/_/g' {} \;
> Mais évidemment, ça me répond "/opt/audio/un artiste/un album/ Aucun
> fichier ou répertoire de ce type" vu que le répertoire "un artiste" est
> devenu "un_artiste". J'espère me faire bien comprendre.
> Donc je cherche une commande, un script qui pourrait remplacer tous les
> espaces en underscores en une seule fois.
>
> Vous auriez ça sous le coude ?
>
> Cordialement,
>
> Nicolas Roudninski
>
Le script que j'ai fais n'est pas forcément le plus simple, mais je
l'avais déjà pour une autre tâche et il s'avère que j'ai pu l'adapter
pour renommer des fichiers. La difficulté en fait c'est de travailler
sur plusieurs dossiers sur plusieurs niveaux tout en les renommant.
Le script travaille avec un dossier temporaire dans lequel seront copiés
les fichiers et dossiers renommé pour ensuite être recopiés dans le
dossier d'origine.
Il faut juste éditer les deux premières variables avec le dossier cible
ainsi qu'un dossier temporaire vide (si possible sur la même partition),
et exécuter le script. Tu peux faire un essai sur un dossier de test
avant comprenant des fichiers avec espaces et d'autres sans, mais j'ai
testé et ça fonctionne bien.
#!/bin/bash
#indiquer le dossier à traiter dans cette variable
dir_from="/home/user/dossier/"
#indiquer un dossier temporaire
tmp_dir="/home/user/dossier_tmp/"
#variable init (ne pas éditer)
array_dir_count1=1
array_dir_count2=0
error=0
dir_array[$array_dir_count2]="$dir_from"
dir_to_array[$array_dir_count2]="$tmp_dir"
if [ "$tmp_dir" != "" ]
then
ls_tmp_dir=`ls "${dir_to_array[$array_dir_count2]}"`
if [ "$ls_tmp_dir" != "" ]
then
echo "Le répertoire temporaire n'est pas vide"
error=5
fi
else
echo "pas de répertoire temporaire configuré"
error=7
fi
if [ ! -w "${dir_to_array[$array_dir_count2]}" ]
then
echo "Le répertoire temporaire n'est pas accessible en écriture"
error=6
fi
until [ "${dir_array[$array_dir_count2]}" == "" ]
do
if [ "$error" -eq "0" ]
then
ls_dir=`ls "${dir_array[$array_dir_count2]}"`
ls_dir=${ls_dir// /@@@@}
for file in $ls_dir
do
file_org=${file//@@@@/ }
file_des=${file//@@@@/_}
input="${dir_array[$array_dir_count2]}/$file_org"
output="${dir_to_array[$array_dir_count2]}/$file_des"
if [ -d "$input" ]
then
echo "$input is a directory"
dir_array[$array_dir_count1]="$input"
dir_to_array[$array_dir_count1]="$output"
if [ ! -d "$output" ]
then
if mkdir "$output"
then
echo "$output created"
else
error=4
fi
fi
(( array_dir_count1++ ))
fi
if [ -f "$input" ]
then
echo "$input is a file"
if [ -e "$output" ]
then
output="$output.1"
fi
if mv "$input" "$output"
then
echo "file $input renemaded as $output"
else
error=1
fi
fi
done
#incrémente l'array
(( array_dir_count2++ ))
else
echo "Error $error"
exit $error
fi
done
if [ "$error" -eq "0" ]
then
if rm -rf "$dir_from"/*
then
if mv "$tmp_dir"/* "$dir_from"/
then
echo "Done"
else
erro=3
fi
else
error=2
fi
fi
exit $error
Si jamais tu as dans le même dossier deux fichiers ayant le même nom,
mais un avec des underscores et l'autre avec des espaces, le script en
renommera un avec .1 à la fin (par exemple "piste_01.ogg" et "piste
01.ogg" deviendront "piste_01.ogg" et piste_01.ogg.1", avec les dossiers
par contres, les contenues seront fusionnés (par exemple avec deux
dossiers "The Doors" et "The_Doors"). Le code utilisé pour remplacer les
espaces dans le script est @@@@, change le si tu as des fichiers
contenant quatre arobases dans leur nom (ce qui est peu probable).
Si tu en as la possibilité, fait un backup quand même avant, j'ai bien
testé le script, mais on est pas à l'abri d'une situation d'erreur à
laquelle je n'aurais pas pensé. Et si tu es paranos comme moi et que tu
as l'espace disque suffisant, remplace le mv par un cp à la ligne 71 et
efface ou commente le code entre les lignes 87 et 100 (incluses), tu
auras une copie des fichiers renommés dans le dossier temporaire que tu
pourra vérifier avant d'effacer les autres.
Je joins le script en pièce jointe pour éviter les erreurs de copier coller.
Cordialement
Christophe
#!/bin/bash
#indiquer le dossier à traiter dans cette variable
dir_from="/home/user/dossier/"
#indiquer un dossier temporaire
tmp_dir="/home/user/dossier_tmp/"
#variable init (ne pas éditer)
array_dir_count1=1
array_dir_count2=0
error=0
dir_array[$array_dir_count2]="$dir_from"
dir_to_array[$array_dir_count2]="$tmp_dir"
if [ "$tmp_dir" != "" ]
then
ls_tmp_dir=`ls "${dir_to_array[$array_dir_count2]}"`
if [ "$ls_tmp_dir" != "" ]
then
echo "Le répertoire temporaire n'est pas vide"
error=5
fi
else
echo "pas de répertoire temporaire configuré"
error=7
fi
if [ ! -w "${dir_to_array[$array_dir_count2]}" ]
then
echo "Le répertoire temporaire n'est pas accessible en écriture"
error=6
fi
until [ "${dir_array[$array_dir_count2]}" == "" ]
do
if [ "$error" -eq "0" ]
then
ls_dir=`ls "${dir_array[$array_dir_count2]}"`
ls_dir=${ls_dir// /@@@@}
for file in $ls_dir
do
file_org=${file//@@@@/ }
file_des=${file//@@@@/_}
input="${dir_array[$array_dir_count2]}/$file_org"
output="${dir_to_array[$array_dir_count2]}/$file_des"
if [ -d "$input" ]
then
echo "$input is a directory"
dir_array[$array_dir_count1]="$input"
dir_to_array[$array_dir_count1]="$output"
if [ ! -d "$output" ]
then
if mkdir "$output"
then
echo "$output created"
else
error=4
fi
fi
(( array_dir_count1++ ))
fi
if [ -f "$input" ]
then
echo "$input is a file"
if [ -e "$output" ]
then
output="$output.1"
fi
if mv "$input" "$output"
then
echo "file $input renemaded as $output"
else
error=1
fi
fi
done
#incrémente l'array
(( array_dir_count2++ ))
else
echo "Error $error"
exit $error
fi
done
if [ "$error" -eq "0" ]
then
if rm -rf "$dir_from"/*
then
if mv "$tmp_dir"/* "$dir_from"/
then
echo "Done"
else
erro=3
fi
else
error=2
fi
fi
exit $error
Reply to: