Czy lepiej jest używać $ (pwd) czy $ PWD?

35

Spotkałem się BASEDIR=$(pwd)w skrypcie.

Czy są jakieś zalety lub wady w stosunku do używania BASEDIR="$PWD", które $PWDmogą być nadpisane?

Minix
źródło
3
trochę informacji na unix.stackexchange.com/a/79621
Stéphane Chazelas
@ StéphaneChazelas Bardzo interesujące napisanie. Jestem dopiero w połowie i będę kontynuować, ale o ile rozumiem, lepiej jest używać $(pwd), ponieważ $PWDw niektórych okolicznościach może stać się nieaktualny.
Minix,
2
tylko w niektórych powłokach (na przykład nie bash, dash, zsh lub ksh93) pwdpotencjalnie da ci mniej przestarzałych informacji niż $PWDw niektórych przypadkach narożnych. $(pwd)z drugiej strony nie działa, jeśli bieżący katalog kończy się znakami nowej linii, oznacza rozwidlenie procesu (z wyjątkiem ksh93) i użycie dodatkowych zasobów. Mój pogląd jest stosowanie $PWDod $(pwd -P), to nie warto korzystać $(pwd).
Stéphane Chazelas,
1
na dole stephane wspomina o użyciu cd -P -- "$dir". jeśli masz jakiekolwiek wątpliwości co do wartości $PWD, zawsze możesz cd -P .najpierw. może to być również korzystne, ponieważ dostajesz to, co $PWDbyło wcześniej, $OLDPWDi możesz je później porównać - a następna cd ...; cd -sekwencja z pewnością zaprowadzi cię z powrotem do miejsca, w którym jesteś teraz.
mikeserv

Odpowiedzi:

41

Jeśli bash się napotka $(pwd), wykona polecenie pwd i zastąpi $(pwd)wyjściem tego polecenia. $PWDjest zmienną, która prawie zawsze jest ustawiona. pwd to wbudowane polecenie powłoki od dłuższego czasu.

Tak $PWDsię nie powiedzie, jeśli ta zmienna nie jest ustawiona i $(pwd)zawiedzie, jeśli używasz powłoki, która nie obsługuje $()konstrukcji, co według mnie dość często zdarza się. Więc skorzystałbym $PWD.

Jak każdy nerd mam własny samouczek dotyczący skryptowania powłoki

Thorsten Staerk
źródło
6
Miałem wrażenie, że `command`składnia jest niepożądana i $(command)należy ją preferować. O ile wiem, ten ostatni jest zgodny z POSIX, ale nie jestem w 100% pewien.
Minix,
6
@Minix $()Rzeczywiście jest to określone przez POSIX, więc poza wcześniejszym POSIXem /bin/shdostępnym na Solarisie 10 i starszych i cshpochodnych powłokach, wątpię, aby wiele innych popularnych powłok nie posiadało tej funkcji.
jlliagre
@Minix: Oto ostatnie pytanie na tej stronie, które ilustruje jeden problem z używaniem backticks zamiast$()
PM 2Ring
poprawne, zamiast $ () można było użyć backticków, ale nie będzie to możliwe kaskadowo, więc nie wspomniałem o tym
Thorsten Staerk
1
Fajna minimapa na twoim tutorialu ....
kbtzr
6

Należy również wspomnieć, że $PWDjest to pożądane ze względu na jego wydajność. Jako zmienna powłoki może być rozwiązana niemal natychmiast. $(pwd)jest nieco bardziej mylące. Jeśli przeprowadzisz inspekcję man 1 bulitinw systemie za pomocą Bash, zobaczysz, że pwdjest to wbudowane polecenie, które może prowadzić do przekonania, że ​​będzie ono równie szybkie, jak dostęp do zmiennej. Jednak $()konstrukcja zawsze uruchamia nową podpowłokę (nowy proces) w celu uruchomienia jej zawartości, niezależnie od tego, co jest w środku. To samo dotyczy backticks. Rzeczywiście, kiedy go porównuję:

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)

Dostaję 1,52 sekundy na $(pwd)połączenie i 0,018 sekundy na $PWD. W miarę możliwości należy unikać niepotrzebnego uruchamiania podpowłoki, a także wszelkich innych procesów zewnętrznych. Są znacznie droższe niż wywołania funkcji, do których możesz być przyzwyczajony w innych językach.

markasoftware
źródło
To ciekawe podejście, ale nie wiem, czy martwię się wydajnością moich skryptów powłoki. Zastanawiam się również, jak zmieniłaby się wydajność, gdyby pwd zmieniał się między zapytaniami.
Minix,
@Minix Zmodyfikowałem skrypt tak, aby ciało pętli było echo $PWD; pushd ..; echo $PWD; popd(z dodatkowymi >/dev/nullpo każdej instrukcji), i zajmuje to 0,05 sekundy. Następnie usunąłem instrukcje echa (tylko pushd / popd) i zajęło to 0,03. Tak więc czas na echo $PWDnadal wynosił około 0,01 sekundy. Zrobiłem coś podobnego $(pwd)i zajęło to 2,2 sekundy dla każdej pętli, więc 1,1 sekundy na $(pwd)połączenie.
markasoftware
Nie jestem zbyt wybredny, ale mogę sobie wyobrazić, że obliczenia, które zastąpiłyby, $PWDzostałyby wykonane w tle przed oceną instrukcji echa. Ale najwyraźniej dostęp $PWDjest wciąż znacznie szybszy, więc jeśli kompatybilność nie stanowi problemu, jest to zdecydowanie powód, aby wybierać między sobą. Dziękujemy za pracę nad tak dokładnym testowaniem. :)
Minix,