Évitez de remplacer des espaces lorsque vous renommez des fichiers

10

J'essaie de renommer des fichiers comme celui-ci:

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 modifier la commande sed pour la faire inclure des espaces avec les caractères spécifiés? J'ai essayé d'utiliser \s mais ça ne marche pas ...

EDIT:
Par exemple: le fichier trip: hill doit être renommé: trip_ hill , mais la commande ci-dessus le rend trip__hill .

    
posée ojenn 22.12.2017 - 14:39
la source

2 réponses

12

Ne pas analyser 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

Ensuite:

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

Notes

  • supprimez -n après le test pour renommer les fichiers
  • -- end-of-options au cas où un fichier commence par -
  • [^-A-Za-z0-9_ .] des caractères que nous ne souhaitons pas remplacer - mettez - en premier ou en dernier afin qu'il ne puisse pas indiquer d'intervalle (il est traité littéralement dans ces positions).
  • Les espaces peuvent être inclus dans la classe
  • . est traité littéralement (dans d'autres contextes d'expression régulière, il représente n'importe quel caractère et doit être échappé).

Ceci fonctionne aussi dans sed :

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

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

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

Mais avec - à la fin, cela fonctionne:

$ echo 'trip: hill' | sed -e 's/[^A-Za-z0-9._ -]/_/g'
trip_ 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 analyser les noms de fichiers tient!

    
réponse donnée Zanna 22.12.2017 - 15:27
la source
2

Vous pouvez également simplement utiliser le shell, développement des paramètres de Bash . peut faire la substitution:

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

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

    
réponse donnée ilkkachu 25.12.2017 - 20:53
la source

Lire d'autres questions sur les étiquettes