Disons que je veux stocker la commande suivante dans une variable
cd "/cygdrive/c/Program Files/"
Donc je fais ça
dir="cd \"/cygdrive/c/Program Files/\""
Cela devrait stocker la commande pour naviguer dans le répertoire Program Files, donc quand je tape $ dir, il m'emmène dans ce répertoire. Pour vérifier que les citations ont été correctement échappées, je tape
echo $dir
ce qui me donne
cd "/cygdrive/c/Program Files/"
Donc, tout devrait bien fonctionner. Cependant, quand je tape,
$dir
Je reçois
bash: cd: "/cygdrive/c/Program: No such file or directory
Qu'est-ce que je fais mal? J'utilise Cygwin, mais je suppose que ce problème s'applique à bash en général.
Réponses:
Réponse courte: voir BashFAQ # 050 ("J'essaie de mettre une commande dans une variable, mais les cas complexes échouent toujours!").
Réponse longue: lorsque bash analyse une commande, il analyse les guillemets avant de remplacer les variables; il ne revient jamais en arrière et ré-analyse les guillemets dans les valeurs des variables, donc ils finissent par ne rien faire d'utile. Utiliser echo pour vérifier la commande est complètement trompeur car il affiche la commande après son analyse; si vous voulez voir ce qui est réellement exécuté, utilisez soit
set -x
les commandes d'impression shell lors de leur exécution, soit utilisezprintf "%q " $dir; echo
plutôt que l'écho.Si vous souhaitez stocker une commande complexe (c'est-à-dire avec des espaces ou d'autres caractères spéciaux dans les "mots"), vous devez la placer dans un tableau au lieu d'une simple variable de texte, puis la développer avec l'idiome `" $ { tableau [@]} ", comme ceci:
Maintenant, si le but est de créer un raccourci facile à taper, ce n'est clairement pas la voie à suivre. Utilisez plutôt un alias ou une fonction shell:
ou
la source
Lorsque bash se développe
$dir
, il n'effectue que la division et la globalisation des mots. Fractionnement mot produit trois mots:cd
,"/cygdrive/c/Program
etFiles/"
. Ensuite, la commande à exécuter estcd
avec deux arguments;cd
ne regarde que son premier argument"/cygdrive/c/Program
, qui n'est pas un répertoire existant.Si vous souhaitez effectuer une évaluation complète du shell sur le contenu d'une variable, utilisez
eval
:Notez que vous avez besoin des guillemets doubles
$dir
, sinon le fractionnement de mots serait d'abord effectué, puiseval
concaténerait ses arguments avec des espaces. Cela se produirait ici, mais irait mal en général (par exemple, s'il y avait deux espaces consécutifs dans un nom de fichier).Cependant, une chaîne n'est pas le bon moyen de stocker une commande shell que vous souhaitez exécuter. Sauf si vous avez une exigence inhabituelle, vous devez plutôt utiliser une fonction:
Si vous êtes vraiment intéressé à taper
$dir
pour basculer vers un répertoire particulier et ce n'est pas seulement un exemple simple, depuis bash 4, mettezshopt -s autocd
votre.bashrc
et définissezaprès quoi vous pouvez taper juste
"/cygdrive/c/Program Files/"
ou"$dir"
à l'invite du shell pour basculer vers ce répertoire. Vous avez toujours besoin des guillemets$dir
; si vous n'aimez pas cela, utilisez zsh au lieu de bash.la source
Stocker des commandes dans des variables n'est généralement pas une bonne idée. C'est à cela que servent les fonctions et les alias.
Plutôt que
essayez l'un d'eux:
ou
ou
Le premier formulaire, stockant le nom du répertoire dans une variable, signifie un peu plus de frappe, mais c'est plus clair lorsque vous exécutez la commande que vous faites
cd
. Le second est le plus proche de ce que vous essayez d'accomplir. (Je n'utilise pas beaucoup d'alias en bash; je ne sais pas vraiment quel avantage ils ont sur les fonctions.)ÉDITER :
Et
dir
c'est probablement un mauvais nom pour un alias ou une fonction, car il existe une commande existante sous ce nom (c'est essentiellement une version dels
, du moins si vous avez des coreutils GNU).la source
Storing commands in variables is generally not a good idea. That's what functions and aliases are for.
Essayer
Mais encore plus précisément:
/programming/4334467/cygwin-using-a-path-variable-containing-a-windows-path-with-a-space-in-it
la source