Est-il préférable d'utiliser $ (pwd) ou $ PWD?

35

J'ai rencontré BASEDIR=$(pwd)dans un script.

Y a-t-il des avantages ou des inconvénients par rapport à l'utilisation BASEDIR="$PWD", autres que peut-être, qui $PWDpourraient être remplacés?

Minix
la source
3
Quelques infos sur unix.stackexchange.com/a/79621
Stéphane Chazelas
@ StéphaneChazelas Rédaction très intéressante. Je ne suis qu'à mi-parcours et je vais continuer, mais d'après ce que j'ai compris, il est préférable de l'utiliser $(pwd), car elle $PWDpeut devenir obsolète dans certaines circonstances.
Minix
2
seulement dans certains shells (pas bash, dash, zsh ou ksh93 par exemple) pwdvous donneront potentiellement moins d’informations périmées que $PWDdans certains cas. $(pwd)en revanche, cela ne fonctionne pas si le répertoire en cours se termine par des caractères de nouvelle ligne, ce qui signifie qu’il faut bricoler un processus (sauf dans ksh93) et utiliser des ressources supplémentaires. Mon point de vue est l'utilisation $PWDde $(pwd -P), ce n'est pas la peine d'utiliser $(pwd).
Stéphane Chazelas
1
en bas, Stéphane mentionne utiliser cd -P -- "$dir". s'il y a le moindre doute sur la valeur de $PWDvous, vous pouvez toujours d' cd -P .abord. cela peut également être bénéfique dans la mesure où vous obtenez également ce qui $PWDétait auparavant $OLDPWDet que vous pouvez donc les comparer par la suite - et la cd ...; cd -séquence suivante ne manquera pas de vous ramener à votre situation actuelle.
mikeserv

Réponses:

41

Si bash rencontre $(pwd) il exécutera la commande pwd et le remplacera $(pwd)par la sortie de cette commande. $PWDest une variable qui est presque toujours définie. pwd est une commande shell intégrée depuis longtemps.

Donc $PWDéchouera si cette variable n’est pas définie et $(pwd)échouera si vous utilisez un shell qui ne supporte pas le$() construction, ce qui, selon mon expérience, est assez souvent le cas. Donc, je voudrais utiliser $PWD.

Comme chaque nerd, j'ai mon propre tutoriel de script shell

Thorsten Staerk
la source
6
J'avais l'impression que la `command`syntaxe n'était pas souhaitable et $(command)qu'il fallait la préférer. Pour autant que je sache, ce dernier est conforme à POSIX, mais je ne suis pas sûr à 100%.
Minix
6
@Minix The $()est en effet spécifié par POSIX. Par conséquent, en dehors du pré-POSIX /bin/shdisponible sur Solaris 10 et les cshshell plus anciens et dérivés, je doute que de nombreux autres shell classiques ne disposent pas de cette fonctionnalité.
jlliagre
@Minix: Voici une question récente sur ce site qui illustre un problème avec l'utilisation de backticks au lieu de$()
PM 2Ring
correct, au lieu de $ () vous pouvez utiliser des backticks, mais cela ne sera pas cascadable, donc je ne l’ai pas mentionné
Thorsten Staerk
1
Belle mini-carte dans votre tutoriel ....
kbtzr
6

Il convient également de mentionner que cela $PWDest souhaitable en raison de ses performances. En tant que variable shell, elle peut être résolue presque instantanément. $(pwd)est un peu plus déroutant. Si vous inspectez man 1 bulitinun système avec Bash, vous verrez que pwdc'est une commande intégrée, ce qui peut vous amener à croire qu'elle sera aussi rapide que d'accéder à une variable. Cependant, la $()construction lance toujours un nouveau sous-shell (un nouveau processus) pour exécuter son contenu, quel que soit son contenu. La même chose vaut pour les backticks. En effet, quand je le compare:

echo 'Benchmarking $(pwd)...'
time (for i in {1..1000}; do echo $(pwd) > /dev/null; done)
echo 'Benchmarking $PWD...'
time (for i in {1..1000}; do echo $PWD > /dev/null; done)

Je reçois 1,52 seconde pour l’ $(pwd)appel et 0,018 seconde pour $PWD. Le lancement inutile de sous-réservoirs, ainsi que tout autre processus inutile, doit être évité autant que possible. Ils sont beaucoup plus coûteux que les appels de fonctions auxquels vous pourriez être habitué dans d'autres langues.

logiciel de marquage
la source
C'est un point de vue intéressant, mais je ne sais pas si je suis préoccupé par les performances de mes scripts shell. Je me demande également comment les performances changeraient si le pwd change entre les interrogations.
Minix le
@Minix J'ai modifié mon script pour que le corps de la boucle soit echo $PWD; pushd ..; echo $PWD; popd(avec supplémentaire >/dev/nullaprès chaque instruction), et cela prend 0,05 seconde. J'ai ensuite supprimé les instructions echo (uniquement pushd / popd) et il a fallu 0,03. Donc, le temps echo $PWDétait encore d'environ 0,01 seconde. J'ai fait quelque chose de similaire avec $(pwd), et cela a pris 2,2 secondes pour chaque boucle, donc 1,1 seconde par $(pwd)appel.
Logiciel de marque du
Ne pas être trop difficile, mais je peux imaginer, que le calcul, qui remplacerait $PWD serait effectué en tâche de fond avant l'évaluation des déclarations d'écho. Mais il est clair que l’accès $PWDest toujours beaucoup plus rapide, donc si la compatibilité n’est pas un problème, c’est une bonne raison de choisir l’un sur l’autre. Merci pour le travail en testant cela si bien. :)
Minix