Évitez de remplacer des espaces lorsque vous renommez des fichiers

J’essaie de renommer des fichiers comme ceci:

for file in *; do mv -i "$file" "$(echo "$file" | sed -e 's/[^A-Za-z0-9._-]/_/g')"; done 

Mais la commande sed remplace tous les espaces par _ .

Comment puis-je éditer la commande sed pour l’inclure des espaces avec les caractères spécifiés? J’ai essayé d’utiliser \s mais ça ne marche pas …

MODIFIER:
Par exemple: le fichier sortingp: hill , devrait être renommé: sortingp_ hill , mais la commande ci-dessus le rend sortingp__hill .

    Ne pas parsingr les noms de fichiers avec sed ! La sortie de echo "$file" peut ne pas être fiable.

    Utilisez rename . Le 17.10, vous devez d’abord l’installer

     sudo apt install rename 

    Alors:

     rename -n -- 's/[^-A-Za-z0-9_ .]/_/g' * 

    Remarques

    • remove -n après le test pour renommer les fichiers
    • -- fin des options au cas où un fichier commence par -
    • [^-A-Za-z0-9_ .] Caractères que nous ne voulons pas remplacer – mettre - premier ou en dernier afin qu’il ne puisse pas indiquer une plage (il est traité littéralement dans ces positions).
    • Les espaces peuvent être inclus dans la classe
    • . est traité littéralement (dans d’autres contextes regex, il représente n’importe quel caractère et doit être évité).

    Cela fonctionne aussi dans sed :

     $ echo 'sortingp: hill' | sed 's/[^-A-Za-z0-9 _.]/_/g' sortingp_ hill 

    Si j’ajoute un espace à la fin de votre version, j’obtiens une erreur:

     $ echo 'sortingp: hill' | sed -e 's/[^A-Za-z0-9._- ]/_/g' sed: -e expression #1, char 22: Invalid range end 

    Mais avec - à la fin, ça marche:

     $ echo 'sortingp: hill' | sed -e 's/[^A-Za-z0-9._ -]/_/g' sortingp_ hill 

    Alors peut-être que la position du trait d’union a causé votre problème lorsque vous avez ajouté l’espace. Mais le conseil de ne pas parsingr les noms de fichiers est valable!

    Vous pouvez également simplement utiliser le shell, le développement des parameters de Bash peut effectuer une substitution:

     for f in ./* ; do mv "$f" "${f//[^-A-Za-z0-9._ ]/_}" done 

    La double barre oblique lui dit de remplacer toutes les correspondances, à part cela, la syntaxe est simple.