web-dev-qa-db-fra.com

Comment remplacer les espaces dans tous les noms de fichiers par un trait de soulignement sous Linux à l'aide du script Shell?

J'ai essayé de suivre le script Shell qui devrait remplacer les espaces de tous les noms de fichiers xml

for xml_file in $(find $1 -name "* .xml" -type f);
do
 echo "removing spaces from XML file:" $xml_file
 mv "$xml_file" "${xml_file// /_}";
done

Supposons que j'ai un fichier xml avec le nom xy z.xml, alors cela donne:

removing spaces from XML file: /home/krishna/test/xy
mv: cannot stat `/home/krishna/test/xy': No such file or directory
removing spaces from XML file: .xml
mv: cannot stat `z.xml': No such file or directory
20
krishna

Utilisez ceci avec bash:

find $1 -name "* *.xml" -type f -print0 | \
  while read -d $'\0' f; do mv -v "$f" "${f// /_}"; done

find recherchera les fichiers avec un espace dans le nom. Les noms de fichiers seront imprimés avec un octet nul (-print0) comme délimiteur pour gérer également les noms de fichiers spéciaux. Puis le read intégré lit les noms de fichiers délimités par le nullbyte et enfin mv remplace les espaces par un trait de soulignement.

EDIT: Si vous voulez aussi supprimer les espaces dans les répertoires, c'est un peu plus compliqué. Les répertoires sont renommés et ne sont plus accessibles par le nom find find. Essaye ça:

find -name "* *" -print0 | sort -rz | \
  while read -d $'\0' f; do mv -v "$f" "$(dirname "$f")/$(basename "${f// /_}")"; done

Le sort -rz inverse l'ordre des fichiers, de sorte que les fichiers les plus profonds d'un dossier soient les premiers à se déplacer et que le dossier lui-même sera le dernier. Ainsi, il n'y a jamais de dossiers renommés avant que tous les fichiers et dossiers ne soient renommés à l'intérieur. La commande mv dans la boucle est également un peu modifiée. Dans le nom cible, nous supprimons uniquement les espaces dans le nom de base du fichier, sinon il ne serait pas accessible.

32
chaos
  1. Utilisation de rename

    find . -type f -name "* *.xml" -exec rename "s/\s/_/g" {} \;
    

    ou avec $1

    find "$1" -type f -name "* *.xml" -exec rename "s/\s/_/g" {} \;
    
  2. Utilisation de mv

    find . -type f -name "* *.xml" -exec bash -c 'mv "$0" "${0// /_}"' {} \;
    

    ou avec $1

    find "$1" -type f -name "* *.xml" -exec bash -c 'mv "$0" "${0// /_}"' {} \;
    
21
A.B.

C'est une méthode que j'ai trouvée face au même problème:

for f in *; do mv "$f" `echo $f | tr ' ' '_'`; done

J'écrivais un fichier de script bash pour mettre à jour automatiquement mes certificats SSL.

2
NekoMisaki

Utilisez rename:

rename 's/\s/_/g' ./*.xml

Pas besoin de find :)

1
Jan Werkhoven