350 votes

Comment remplacer les espaces dans les noms de fichiers en utilisant un script bash

Quelqu'un peut-il recommander une solution sûre pour remplacer récursivement les espaces par des caractères de soulignement dans les noms de fichiers et de répertoires à partir d'un répertoire racine donné ? Par exemple :

$ tree
.
|-- a dir
|   `-- file with spaces.txt
`-- b dir
    |-- another file with spaces.txt
    `-- yet another file with spaces.pdf

devient :

$ tree
.
|-- a_dir
|   `-- file_with_spaces.txt
`-- b_dir
    |-- another_file_with_spaces.txt
    `-- yet_another_file_with_spaces.pdf

10 votes

Que voulez-vous qu'il se passe s'il y a un fichier appelé foo bar et un autre fichier appelé foo_bar dans le même répertoire ?

0 votes

Bonne question. Je ne voudrais pas écraser les fichiers existants ou perdre des données. Il devrait le laisser inchangé, idéalement en imprimant un avertissement, mais c'est probablement trop demander.

495voto

Naidim Points 372

J'utilise :

for f in *\ *; do mv "$f" "${f// /_}"; done

Bien qu'il ne soit pas récursif, il est assez rapide et simple. Je suis sûr que quelqu'un ici pourrait le mettre à jour pour qu'il soit récursif.

El ${f// /_} utilise le mécanisme d'expansion des paramètres de bash pour remplacer un motif dans un paramètre par la chaîne fournie. La syntaxe pertinente est ${parameter/pattern/string} . Voir : https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html o http://wiki.bash-hackers.org/syntax/pe .

11 votes

C'est simple et ça marche sur Mac. rename et il est trop difficile de l'installer avec brew )

7 votes

Réponse géniale. J'ai utilisé for d in *\ *; do mv "$d" "${d// /}"; done non sous le score.

1 votes

Contrairement à la réponse "find -name", celle-ci a fonctionné sur mon OS X ! Merci Monsieur !

391voto

Dennis Williamson Points 105818

Utilisez rename (alias prename ) qui est un script Perl qui peut être déjà sur votre système. Faites-le en deux étapes :

find . -name "* *" -type d | rename 's/ /_/g'    # do the directories first
find . -name "* *" -type f | rename 's/ /_/g'

Sur la base de Jürgen et capable de traiter plusieurs couches de fichiers et de répertoires en une seule fois en utilisant la version "Revision 1.5 1998/12/18 16:16:31 rmb1" de /usr/bin/rename (un script Perl) :

find /tmp/ -depth -name "* *" -execdir rename 's/ /_/g' "{}" \;

7 votes

Pas besoin de deux étapes : Utilisez la recherche en profondeur : find dir -depth

0 votes

Hmm Dennis, que se passerait-il si vous avez des répertoires "a a", "a a/b b" ? N'essaierait-il pas de renommer "a a" en "a_a" et ensuite "a a/b b" (qui n'existe plus) en "a_a/b_b" ?

4 votes

Oh, je viens de lire le rename manpage (je ne connaissais pas l'outil) et je pense que vous pouvez optimiser votre code en modifiant s/ /_/g a y/ /_/ ;-)

123voto

find . -depth -name '* *' \
| while IFS= read -r f ; do mv -i "$f" "$(dirname "$f")/$(basename "$f"|tr ' ' _)" ; done

Je n'ai pas réussi à le faire au début, car je n'ai pas pensé aux répertoires.

1 votes

Ça marche comme un charme. Merci Michael.

0 votes

Dennis, bonne prise, facilement corrigée en mettant IFS='' devant read . Aussi, pour ce que je peux dire par d'autres commentaires, sort peut être abandonnée au profit de l'étape -depth option pour find .

1 votes

Ne fonctionne pas si un nom de fichier contient un \ (barre oblique inversée). Peut être corrigé en ajoutant un -r option à lire.

50voto

user78274 Points 41

Vous pouvez utiliser detox par Doug Harple

detox -r <folder>

16voto

Jürgen Hötzel Points 6613

A trouver/renommer solution. renommer fait partie de util-linux.

Vous devez d'abord descendre en profondeur, car un nom de fichier en espace blanc peut faire partie d'un répertoire en espace blanc :

find /tmp/ -depth -name "* *" -execdir rename " " "_" "{}" ";"

0 votes

Je n'obtiens aucun changement quand j'utilise le vôtre.

0 votes

Vérifiez la configuration de util-linux : $ rename --version rename (util-linux-ng 2.17.2)

0 votes

Grepping /usr/bin/rename (un script Perl) révèle "Revision 1.5 1998/12/18 16:16:31 rmb1"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X