web-dev-qa-db-fra.com

Exécuter une commande stockée dans une variable $

J'ai fait un script où j'ai écrit:

 COMMAND = "/ usr/bin/exiftool $ PATH_NAME" 
 .... code .... 
 $ COMMAND 

La variable $ PATH_NAME est assignée dynamiquement dans une boucle while. La commande fonctionne correctement jusqu'à ce qu'elle rencontre des fichiers contenant des espaces (par exemple, PATH_NAME = "Add Driver.png"). La sortie de la console est:

 Fichier non trouvé: ./Add
Fichier non trouvé: driver.png 

La commande devrait être:

/ usr/bin/exiftool ./Add driver.png

Je pense que le problème est donné par les espaces dans le $ PATH_NAME. J'ai aussi essayé d'exécuter directement la commande:

 eval "/ usr/bin/exiftool $ PATH_NAME" 

Mais même erreur de sortie. Une idée pour résoudre le problème? Merci.

4
Labo29

Au lieu d'utiliser des chaînes simples, construisez votre commande en utilisant des tableaux. Les tableaux fournissent une interface pratique: Si a est un tableau, alors "${a[@]}" (notez les guillemets) se développe en chaque élément de a, sans le fractionnement ou l’agrégation de champ supplémentaire (pour que les espaces, ainsi que les caractères génériques), intact).

Exemple:

$ a=(printf "|%s|\n" "foo   bar" "*")
$ echo ${a[@]}
printf |%s|\n foo bar bin boot dev etc home lib lib64 lost+found mnt opt proc root run sbin srv sys tmp usr var

Notez comment le * a été développé et comment les espaces supplémentaires entre foo et bar ont été perdus. Mais avec le "${a[@]}", ceux-ci sont conservés:

$ echo "${a[@]}"
printf |%s|\n foo   bar *

C'est idéal pour construire des commandes. Maintenant, vous pouvez faire:

$ "${a[@]}"
|foo   bar|
|*|

Voir? Les arguments ont été parfaitement conservés.

Alors faites:

COMMAND=(/usr/bin/exiftool "$PATH_NAME")
"${COMMAND[@]}"
6
muru

Pour des explications plus détaillées sur la façon dont Bash interprète les espaces, je vous recommande de lire ceci: Variables Bash et substitution de commandes

Solution propre

L'élargissement d'une variable peut entraîner des résultats inattendus et parfois catastrophiques si la variable contient des caractères spéciaux:

user@Host:~$ do_something $some_variable

L'élargissement d'une variable entre guillemets peut éviter de tels problèmes:

user@Host:~$ do_something "$some_variable"

Explication

Le cas rencontré ici est décrit à la fin du post:

Les dangers des variables non citées

Dans un monde idéal, tout le monde garderait ses valeurs de chaîne courtes et sans espace/nouvelle ligne, ni aucun autre caractère spécial.

[...]

Mais lorsque les gens commencent à ajouter des caractères spéciaux aux noms de fichiers, tels que des espaces, le développement de variables, sans l'utilisation de guillemets doubles, peut s'avérer dangereux.

[...]

La principale chose à retenir ici est donc: double-citez vos références de variable autant que possible .

1
darckcrystale

le point de Glenn Jackman est bien pris. Mais, pour résoudre votre cas d'utilisation immédiate, qu'en est-il des backticks? Ainsi:

`echo $COMMAND`

Par exemple, cela fonctionne:

COMMAND='ls /'
`echo $COMMAND`
1
matthewn