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.
Essayer:
for f in *.txt; do mv "$f" "${f// /}"; done
Trois points:
Les guillemets autour d'une variable Shell ne doivent pas être échappés.
En général, il est conseillé de mettre des guillemets autour de chaque référence à une variable Shell.
${f/ /}
supprime seulement la première occurrence d'un espace. Pour supprimer tous les espaces, utilisez ${f// /}
.
$ 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.
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"