Ist es besser, $ (pwd) oder $ PWD zu verwenden?

35

Ich bin BASEDIR=$(pwd)in einem Drehbuch darauf gestoßen .

Gibt es Vor- oder Nachteile gegenüber der Verwendung BASEDIR="$PWD", die möglicherweise $PWDüberschrieben werden könnten?

Minix
quelle
3
Einige Informationen unter unix.stackexchange.com/a/79621
Stéphane Chazelas
@ StéphaneChazelas Sehr interessant zu schreiben. Ich bin erst auf halbem Weg und werde weitermachen, aber soweit ich es verstanden habe, ist es besser, es zu verwenden $(pwd), da es $PWDunter bestimmten Umständen veraltet sein kann.
Minix
2
Nur in einigen Shells (z. B. Bash, Dash, Zsh oder Ksh93) erhalten Sie pwdmöglicherweise weniger veraltete Informationen als $PWDin einigen Eckfällen. $(pwd)Funktioniert dagegen nicht, wenn das aktuelle Verzeichnis mit Zeilenumbrüchen endet, bedeutet dies, dass ein Prozess abgebrochen wird (außer in ksh93) und zusätzliche Ressourcen verwendet werden. Meine Ansicht ist , die Verwendung $PWDvon $(pwd -P), ist es nicht wert , mit $(pwd).
Stéphane Chazelas
1
unten erwähnt stephane using cd -P -- "$dir". Wenn es irgendwelche Zweifel über den Wert von $PWDdir gibt, kannst du immer cd -P .zuerst. Dies kann auch insofern von Vorteil sein, als Sie auch das bekommen, was $PWDvorher war, $OLDPWDund diese anschließend vergleichen können - und die nächste cd ...; cd -Sequenz wird Sie mit Sicherheit dorthin zurückbringen, wo Sie jetzt sind.
mikeserv

Antworten:

41

Wenn bash auf etwas stößt $(pwd), wird der Befehl pwd ausgeführt und durch $(pwd)die Ausgabe dieses Befehls ersetzt.$PWDist eine Variable, die fast immer gesetzt ist. pwd ist seit langer Zeit ein eingebauter Shell-Befehl.

So $PWDwird scheitern , wenn diese Variable nicht gesetzt ist , und $(pwd)wird fehlschlagen , wenn Sie eine Shell verwenden , die nicht die unterstützt $()Konstrukt , das meiner Erfahrung ist ziemlich oft der Fall ist . Also würde ich verwenden $PWD.

Wie jeder Nerd habe ich mein eigenes Shell-Skript-Tutorial

Thorsten Staerk
quelle
6
Ich hatte den Eindruck, dass die `command`Syntax unerwünscht war und $(command)vorzuziehen ist. Soweit ich weiß, ist Letzteres POSIX-kompatibel, aber ich bin mir nicht zu 100% sicher.
Minix
6
@Minix Das $()wird in der Tat von POSIX spezifiziert, so dass ich bezweifle, dass viele andere Mainstream-Shells diese Funktion nicht haben, wenn /bin/shsie nicht unter Solaris 10 und älteren und cshabgeleiteten Shells verfügbar sind .
Juli
@Minix: Hier ist eine aktuelle Frage auf dieser Website, die ein Problem mit der Verwendung von Backticks anstelle von$()
PM 2Ring 12.12.14
Richtig, anstelle von $ () könnten Sie Backticks verwenden, dies ist jedoch nicht kaskadierbar, daher habe ich es nicht erwähnt
Thorsten Staerk
1
Nizza Minikarte auf Ihrem Tutorial ....
kbtzr
6

Es sollte auch erwähnt werden, dass dies $PWDaufgrund seiner Leistung wünschenswert ist. Als Shell-Variable kann sie fast sofort aufgelöst werden. $(pwd)ist ein bisschen verwirrender. Wenn Sie man 1 bulitinein System mit Bash untersuchen, werden Sie feststellen, dass pwdes sich um einen integrierten Befehl handelt, der Sie möglicherweise zu der Annahme verleitet, dass der Zugriff auf eine Variable genauso schnell erfolgt wie der Zugriff auf eine Variable. Das $()Konstrukt startet jedoch immer eine neue Subshell (einen neuen Prozess), um dessen Inhalt auszuführen, unabhängig davon, was sich darin befindet. Das gleiche gilt für Backticks. In der Tat, wenn ich es benchmarken:

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)

Ich bekomme 1,52 Sekunden für den $(pwd)Anruf und 0,018 Sekunden für $PWD. Unnötiges Starten von Subshells sowie andere fremde Prozesse sollten nach Möglichkeit vermieden werden. Sie sind viel teurer als Funktionsaufrufe, an die Sie in anderen Sprachen gewöhnt sind.

markasoftware
quelle
Das ist eine interessante Einstellung, aber ich weiß nicht, ob ich mir Sorgen um die Leistung meiner Shell-Skripte mache. Ich frage mich auch, wie sich die Leistung ändern würde, wenn sich die pwd zwischen den Abfragen ändert.
Minix
@Minix Ich habe mein Skript so geändert, dass der Loop-Body echo $PWD; pushd ..; echo $PWD; popd(mit zusätzlichen >/dev/nullnach jeder Anweisung) ist, und es dauert 0,05 Sekunden. Ich habe dann die echo-Anweisungen entfernt (nur pushd / popd) und es hat 0.03 gedauert. Die Zeit pro echo $PWDwar also immer noch 0,01 Sekunden oder so. Ich habe etwas Ähnliches mit gemacht $(pwd), und es dauerte 2,2 Sekunden für jede Schleife, also 1,1 Sekunden pro $(pwd)Anruf.
Markasoftware
Um nicht zu wählerisch zu sein, aber ich kann mir vorstellen, dass die Berechnung, die diese ersetzen $PWDwürde, im Hintergrund vor der Auswertung der Echo-Anweisungen erfolgen würde. Der Zugriff $PWDist jedoch immer noch erheblich schneller. Wenn also die Kompatibilität keine Rolle spielt, ist dies definitiv ein Grund, sich gegenseitig zu überlegen. Vielen Dank für die Arbeit, diese so gründlich zu testen. :)
Minix