web-dev-qa-db-fra.com

Dois-je utiliser des guillemets dans les noms de chemin d'accès à l'environnement?

Je suis en train de nettoyer tous mes fichiers de configuration afin de les rendre aussi lisibles que possible. Je cherchais un guide de style sur l'utilisation de guillemets lors de l'exportation de chemins dans, par exemple, un ~/.bashrc fichier:

export PATH="/users/me/path:$PATH"

contre

export PATH=/users/me/path:$PATH

Le guide Google style Shell suggère d'éviter les guillemets pour les noms de chemin. En revanche, de nombreux dépôts de fichiers dotfiles populaires (tels que Zach Holman ici ) utilisent des guillemets. Y a-t-il des situations où il est avantageux d'utiliser des guillemets dans le chemin?

27
Cabbage soup

Pointe du chapeau à @ gniourf_gniourf et @ chepner pour leur aide.

tl; dr

Pour être sûr, double-quote: cela fonctionnera dans tous les cas, sur tous les shells POSIX.

Si vous souhaitez ajouter un chemin basé sur ~, sélectivement laissez le ~/ sans guillemets pour vous assurer que ~ Est développé; par exemple: export PATH=~/"bin:$PATH"Voir ci-dessous pour les règles d'expansion de ~ Dans les affectations de variables.
Alternativement, utilisez simplement $HOME Dans une chaîne simple entre guillemets:
export PATH="$HOME/bin:$PATH"


REMARQUE: ce qui suit s'applique à bash, ksh et zsh, mais PAS à ( principalement) des shells strictement POSIX conformes tels que dash; ainsi, lorsque vous ciblez /bin/sh, vous DEVEZ entre guillemets le RHS de export.[1]

  • Les guillemets doubles sont facultatif, UNIQUEMENT SI la partie littérale de votre RHS (la valeur à attribuer) ne contient aucun espace ni d'autres métacaractères Shell.
  • Que les valeurs des variables référencées contiennent ou non des espaces/métacaractères pas importe - voir ci-dessous.
    • Encore une fois: cela le fait importe avec sh, lorsque export est utilisé, donc toujours entre guillemets.

La raison pour laquelle vous pouvez vous en sortir sans les guillemets doubles dans ce cas est que affectation variable dans les shells POSIX-like interpréter leur RHS différemment que arguments passé à commandes, comme décrit dans section 2.9.1 de la spécification POSIX:

  • Plus précisément, même si initial Séparateur de mots est effectué, il n'est appliqué qu'aux non étendus (bruts) RHS ( c'est pourquoi vous faites avez besoin de citer avec des espaces/métacaractères en littéraux), et non à son résultats.

  • Ceci s'applique uniquement aux instructions d'affectation authentique du formulaire
    <name>=<value> Dans tous Shells de type POSIX
    , c'est-à-dire s'il y a pas de nom de commande avant le nom de la variable; notez que cela inclut les affectations préfixées à une commande pour définir des variables d'environnement ad-hoc pour elle, par exemple, foo=$bar cmd ....

  • Les affectations dans le contexte d'autres commandes doivent toujours être entre guillemets , pour être sûr:

    • Avec sh (dans un Shell (principalement) strictement conforme à POSIX tel que dash) une affectation avec export est traitée comme une commande régulière =, et la partie foo=$bar est traitée comme le 1er argument au export intégré et donc traitée comme d'habitude (sous réserve du fractionnement de Word du result, aussi).
      (POSIX ne spécifie aucune autre commande impliquant une affectation de variable (explicite); declare, typeset et local ne sont pas standard extensions ).

    • bash, ksh, zsh, dans un écart compréhensible de POSIX, étendez également la logique d'affectation à export foo=$bar et typeset/declare/local foo=$bar. En d'autres termes: dans les commandes bash, ksh, zsh, export/typeset/declare/local Sont traitées comme affectations , afin que la citation ne soit pas strictement nécessaire .

      • Peut-être de manière surprenante, dash, qui a également choisi d'implémenter le non - POSIX local builtin[2] , ne lui étend PAS la logique d'affectation; il est cependant cohérent avec son comportement export.
    • Les affectations passées à env (par exemple, env foo=$bar cmd ...) Sont également sujettes à expansion en tant qu'argument de commande et nécessitent donc des guillemets doubles - sauf dans zsh.

      • Que env agit différemment de export dans ksh et bash à cet égard est dû au fait que env est un external utility, alors que export est un Shell intégré.
        (le comportement de zsh fondamentalement diffère de celui des autres shells en ce qui concerne les références de variables non cotées).
  • L'extension Tilde (~) Se produit comme suit dans les instructions d'affectation authentique:

    • En plus du ~ Devant être non cité, comme d'habitude, il n'est également appliqué que:
      • Si le entier RHS est ~; par exemple.:
        • foo=~ # same as: foo="$HOME"
      • Sinon: seulement si les deux des conditions suivantes sont remplies:
        • si ~ démarre la chaîne ou est précédé d'un sans guillemets:
        • si ~ est suivi d'un sans guillemets/.
        • par exemple.,
          foo=~/bin # same as foo="$HOME/bin"
          foo=$foo:~/bin # same as foo="$foo:$HOME/bin"

Exemple

Cet exemple montre que dans bash, ksh et zsh, vous pouvez vous éloigner sans entre guillemets, même lorsque vous utilisez export, mais Je ne le recommande pas.

#!/usr/bin/env bash
# or ksh or zsh - but NOT /bin/sh!

# Create env. variable with whitespace and other Shell metacharacters
export FOO="b:c &|<> d"

# Extend the value - the double quotes here are optional, but ONLY 
# because the literal part, 'a:`, contains no whitespace or other Shell metacharacters.
# To be safe, DO double-quote the RHS.
export FOO=a:$foo # OK - $FOO now contains 'a:b:c &|<> d'

[1] Comme le souligne @gniourf_gniourf: utilisation de export pour modifier la valeur de PATH est facultative, car une fois qu'une variable est marquée comme exportée, vous peut utiliser une affectation régulière (PATH=...) pour modifier sa valeur.
Cela dit, vous pouvez toujours choisir pour utiliser export, afin de rendre explicite que la variable en cours de modification est exportée.

[2] @gniourf_gniourf indique qu'une future version du standard POSIX pourrait introduire le local intégré.

19
mklement0

J'ai utilisé ces réponses ci-dessus lors de la définition des noms de chemin d'accès à l'environnement dans un fichier docker .env, et j'ai obtenu un bit. Je mets cela ici pour quiconque cherche comment définir des variables d'environnement pour docker.

Docker compose lit les variables d'environnement à partir d'un fichier .env qui existe dans le même dossier que docker compose est exécuté comme indiqué ici https://docs.docker.com/compose/env-file.

Cependant, au lieu d'encapsuler la valeur entre guillemets, docker compose a besoin de la variable d'environnement définie sans guillemets, sauf si les guillemets font partie de la valeur. Encore une fois, comme indiqué dans l'url ci-dessus

Il n'y a pas de traitement spécial des guillemets (c'est-à-dire qu'ils feront partie de la VAL, vous avez été averti;)

J'essayais de définir NODE_PATH=./src pour que les chemins absolus fonctionnent dans une application react déployée par docker, mais l'avaient écrite comme NODE_PATH="./src". Cet avertissement m'a sorti du trou de lapin de 4 heures.

2
Fralcon

test 123 est un nom de chemin d'accès valide sous UNIX. Essayer

PATH=test 123

Il renverra:

123: command not found

Ou même

export PATH=test 123

qui reviendra

bash export: `123': not a valid identifier

Répond-il à votre question?

Honnêtement, je ne suivrais pas ces guides de style de quatrième partie . Même si je suis étonné que même Google annonce de si mauvais conseils.

Je suivrais:

(à étendre soigneusement)

2
hek2mgl