J'utiliserais bash et find. Je suis sûr qu'il y a une option plus simple, mais voici ce que j'ai trouvé :
-
Cela permet de traiter les noms de fichiers contenant "/" (find donnera un avertissement, ignorez-le), mais cela ne fonctionnera que sur les fichiers du répertoire courant (pas de sous-répertoires). Je n'ai pas réussi à trouver comment dire à bash ou à find de faire la différence entre un "/" dans un nom de fichier et un "/" qui fait partie du chemin.
for i in $(find . -maxdepth 1 -type f -name "*[\:\;><\@\$\#\&\(\)\?\\\/\%]*" | sed 's/\.\///'); do mv "$i" ${i//[\;><\@\$\#\&\(\)\?\\\/\%]/_}; done
-
Celui-là ne peut pas traiter les noms de fichiers contenant "/" mais il fonctionnera sur tous les fichiers du répertoire courant. et ses sous-répertoires :
for i in $(find . -type f -name "*[\:\;\>\<\@\$\#\&\(\)\?\\\%]*"); do mv "$i" ${i//[\;><\@\$\#\&\(\)\?\\\%]/_}; done
Veillez à testez-les avant de les exécuter . Ils ont bien fonctionné dans les quelques tests que j'ai effectués, mais je n'ai pas été exhaustif. Gardez également à l'esprit que je suis sur un système linux. L'implémentation particulière de find, et peut-être de bash, peut différer sur le vôtre.
EDIT : Changement de la mv $i
à `mv -i $i' fera en sorte que mv vous demande d'écraser un fichier existant.
EDIT2 : Pour gérer les noms de fichiers avec des espaces, vous pouvez modifier la variable bash IFS (Input Field Separator) comme suit (adapté de aquí ) :
SAVEIFS=$IFS; IFS=$(echo -en "\n\b"); for i in $(find . -type f -name "*[\:\;\>\<\@\$\#\&\(\)\?\\\%\ ]*"); do mv "$i" ${i//[\;><\@\$\#\&\(\)\?\\\%\ ]/_}; done; IFS=$SAVEIFS
J'ai également modifié l'expression régulière pour faire correspondre/remplacer les espaces par des caractères de soulignement. Le bit SAVEIFS renvoie simplement la variable IFS à sa configuration d'origine.
EXPLICATION :
for i in $(command); do something $i; done
Il s'agit d'une boucle bash générique. Elle va parcourir la sortie d'une commande, en donnant séquentiellement à la variable $i chacune des valeurs retournées par la commande, et va y faire quelque chose.
find . -maxdepth 1 -type f -name "*[\:\;><\@\$\#\&\(\)\?\\\/\%]*" '
Trouver tous les fichiers du répertoire actuel dont le nom contient l'un des caractères suivants : :;><@$#&()\/%
. Pour en ajouter d'autres, il suffit de les échapper avec "\" (par exemple "\¿") et de les ajouter à la liste entre parenthèses ([ ]). Il est probable que tous ces caractères n'ont pas besoin d'être échappés, mais je ne peux jamais me rappeler quelles sont les variables spéciales dans quel environnement, alors j'échappe tout, juste au cas où.
sed 's/\.\///
Supprime le répertoire courant de la sortie de find, affiche "foo" au lieu de "./foo".
mv "$i" ${i//[\;><\@\$\#\&\(\)\?\\\/\%]/_}
A chaque fois que ce petit scipt boucle, $i sera le nom d'un fichier mal nommé. Cette commande va déplacer (renommer) ce fichier en changeant tous les caractères non désirés en "_". Consultez la rubrique substitution de bash pour plus d'informations.