web-dev-qa-db-fra.com

erreur bash lors du changement de nom des fichiers avec des espaces - mv target n'est pas un répertoire

J'essaie de renommer une série de fichiers contenant des espaces, en les supprimant. Je pensais avoir trouvé la bonne commande bash:

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

Cependant, cela donne l’erreur suivante: "mv: target n’est pas un répertoire" pour chaque fichier. Si je remplace «mv» par «echo mv» dans la commande, la commande mv appropriée est imprimée pour chaque fichier et, si je tape une de ces commandes individuellement, elles fonctionnent. Par exemple, si j'ai 2 fichiers, "a .txt" et "b .txt" et que j'exécute la commande ci-dessus, je reçois:

mv: target 'a.txt' is not a directory
mv: target 'b.txt' is not a directory

Si je tape la commande:

for f in *.txt; do echo mv \"$f\" ${f/ /}; done

Je reçois:

mv "a .txt" a.txt
mv "b .txt" b.txt

J'ai trouvé un autre moyen de le faire, en utilisant "renommer", mais j'aimerais savoir pourquoi cela ne fonctionne pas.

9
Jim Hines

Essayer:

for f in *.txt; do mv "$f" "${f// /}"; done

Trois points:

  1. Les guillemets autour d'une variable Shell ne doivent pas être échappés.

  2. En général, il est conseillé de mettre des guillemets autour de chaque référence à une variable Shell.

  3. ${f/ /} supprime seulement la première occurrence d'un espace. Pour supprimer tous les espaces, utilisez ${f// /}.

Qu'est ce qui ne s'est pas bien passé

$ touch {a,b}" .txt"
$ ls *.txt
a .txt  b .txt
$ for f in *.txt; do mv \"$f\" ${f/ /}; done
mv: target `a.txt' is not a directory
mv: target `b.txt' is not a directory

L'expression \"$f\" ne se comporte pas comme si elle était entre guillemets. Il se développe en deux arguments, tels que "a et .txt", où les guillemets sont traités comme des caractères normaux, tout comme la variable a est un caractère normal. Comme il existe trois arguments pour mv ("a et .txt" et a.txt), mv pense que vous essayez de déplacer les deux premiers arguments vers le troisième et que le troisième doit être un répertoire. Comme le troisième n'est pas un répertoire, un message d'erreur est émis.

21
John1024

Parce que c’est la première chose qui est apparue sur Google lorsque nous avons cherché cette erreur sur Google, j’ai pensé ajouter quelque chose.

Cette erreur se produit si vous avez plus de deux arguments et que le dernier résultat n'est pas un répertoire.

Cela marche:

mv file1.txt output.txt

Cela ne veut pas:

mv file1.txt file2.txt

Dans mon cas, j’étais en train de faire: mv prefix_* output_file_name pour s’assurer que le fichier téléchargé avait un nom consistant, mais qu’un autre fichier était apparu dans le répertoire, avec l’erreur "La cible mv n’était pas un répertoire"

0
sdfgeoff