Comment replace les espaces dans tous les noms de files par un trait de soulignement sous Linux en utilisant un script shell?

J'ai essayé le script shell suivant qui devrait replace les espaces de tous les files 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 file xml avec le nom xy z.xml , alors il 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 

Utilisez ceci avec bash :

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

find searchra les files avec un espace dans le nom. Les noms de files seront imprimés avec un nullbyte ( -print0 ) comme délimiteur pour gérer également les noms de files spéciaux. Ensuite, la read embeddede lit les noms de files 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 directorys, c'est un peu plus compliqué. Les directorys sont renommés puis ne sont plus accessibles par le nom 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 files, de sorte que les files 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 files et dossiers ne soient renommés à l'intérieur. La command mv dans la boucle est un peu modifiée aussi. Dans le nom de la cible, nous supprimons uniquement les espaces dans le nom de base du file, sinon il ne serait pas accessible.

  1. Utiliser le 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. Utiliser 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// /_}"' {} \;