Dans mon environnement Bash, j'utilise des variables contenant des espaces, et j'utilise ces variables dans la substitution de commande.
Quelle est la bonne façon de citer mes variables ? Et comment dois-je faire si ceux-ci sont imbriqués ?
DIRNAME=$(dirname "$FILE")
ou est-ce que je cite en dehors de la substitution ?
DIRNAME="$(dirname $FILE)"
ou les deux ?
DIRNAME="$(dirname "$FILE")"
ou dois-je utiliser des back-ticks ?
DIRNAME=`dirname "$FILE"`
Quel est le bon moyen de le faire? Et comment puis-je vérifier facilement si les devis sont corrects ?
Réponse acceptée :
Dans l'ordre du pire au meilleur :
DIRNAME="$(dirname $FILE)"
ne fera pas ce que vous voulez si$FILE
contient des espaces (ou n'importe quel caractère$IFS
contient actuellement) ou caractères globaux[?*
.DIRNAME=`dirname "$FILE"`
est techniquement correct, mais les backticks ne sont pas recommandés pour l'expansion des commandes en raison de la complexité supplémentaire lors de leur imbrication et du traitement supplémentaire de la barre oblique inverse qui s'y produit.DIRNAME=$(dirname "$FILE")
est correct, mais uniquement parce qu'il s'agit d'une affectation à une variable scalaire (pas de tableau). Si vous utilisez la substitution de commande dans un autre contexte, tel queexport DIRNAME=$(dirname "$FILE")
oudu $(dirname -- "$FILE")
, l'absence de guillemets causera des problèmes si le résultat de l'expansion contient des espaces blancs ou des caractères globaux.DIRNAME="$(dirname "$FILE")"
(sauf pour le--
manquant , voir ci-dessous) est la méthode recommandée. Vous pouvez remplacerDIRNAME=
avec une commande et un espace sans rien changer d'autre, etdirname
reçoit la chaîne correcte.
Pour s'améliorer encore :
DIRNAME="$(dirname -- "$FILE")"
fonctionne si$FILE
commence par un tiret.DIRNAME="$(dirname -- "$FILE" && printf x)" && DIRNAME="${DIRNAME%?x}" || exit
fonctionne même si$FILE
Le nom du répertoire se termine par une nouvelle ligne, puisque$()
coupe les nouvelles lignes à la fin de la sortie, à la fois celle ajoutée pardirname
et celles qui peuvent faire partie des données réelles.
Vous pouvez imbriquer les extensions de commande autant que vous le souhaitez. Avec $()
vous créez toujours un nouveau contexte de citation, vous pouvez donc faire des choses comme ceci :
foo "$(bar "$(baz "$(ban "bla")")")"
Vous ne faites pas je veux essayer ça avec des backticks.