Dziwna różnica między pwd i / bin / pwd

15

Dodałem dowiązanie symboliczne do bieżącego katalogu za pomocą ln -s . aa. Jeśli wykonam cd aa, a następnie wykonam , pwdodpowiedź brzmi /home/sim/aa.

Ale jeśli wykonam /bin/pwd, drukuje /home/sim(bieżący katalog się nie zmienił).

Skąd ta różnica?

użytkownik3581976
źródło

Odpowiedzi:

17

W większości powłok, w tym bash, pwdwbudowana jest powłoka:

$ type -a pwd
pwd is a shell builtin
pwd is /bin/pwd

Jeśli używasz /bin/pwd, musisz użyć -Lopcji, aby uzyskać taki sam wynik jak wbudowany pwd:

$ ln -s . test
$ cd test && pwd
/home/cuonglm/test
$ /bin/pwd
/home/cuonglm
$ /bin/pwd -L
/home/cuonglm/test

Domyślnie /bin/pwdignoruje dowiązania symboliczne i drukuje rzeczywisty katalog.

Od info pwd:

`-L'
`--logical'
     If the contents of the environment variable `PWD' provide an
     absolute name of the current directory with no `.' or `..'
     components, but possibly with symbolic links, then output those
     contents.  Otherwise, fall back to default `-P' handling.

`-P'
`--physical'
     Print a fully resolved name for the current directory.  That is,
     all components of the printed name will be actual directory
     names--none will be symbolic links.

Wbudowane pwddomyślnie zawiera dowiązanie symboliczne, z tą różnicą, że -Pużywana jest opcja lub -o physicalwłączone jest wbudowane ustawianie.

Od man bash:

pwd [-LP]
              Print the absolute pathname of the  current  working  directory.
              The pathname printed contains no symbolic links if the -P option
              is supplied or the -o physical option to the set builtin command
              is  enabled.  If the -L option is used, the pathname printed may
              contain symbolic links.  The return status is 0 unless an  error
              occurs  while  reading  the  name of the current directory or an
              invalid option is supplied.
Cuonglm
źródło
Nie jestem pewien, czy rozumiem, skąd biorą się te różnice
użytkownik3581976,
/bin/pwddomyślnie ignoruje dowiązanie symboliczne, przeczytaj część info pwdmojej odpowiedzi: Wydrukuj w pełni rozpoznaną nazwę dla bieżącego katalogu. Oznacza to, że wszystkie składniki drukowanej nazwy będą rzeczywistymi nazwami katalogów - żaden nie będzie dowiązaniami symbolicznymi.
cuonglm,
@ user3581976: Przejrzyj moją zaktualizowaną, aby wyraźniej.
cuonglm,
Dlaczego istnieje polecenie -L dla pwd, chociaż jest ustawione domyślnie? I czy powłoka nie używa polecenia / bin / pwd do uruchomienia pwd?
user3581976,
2
@ user3581976: Obraz, z którego uruchamiasz powłokę set -o physical, teraz domyślnie pwdjest używana -Popcja, jeśli nie masz -Lopcji, jak wydrukować ścieżkę zawiera dowiązanie symboliczne? Przeczytaj to, https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.htmlaby wiedzieć, co set -o physicalrobi.
cuonglm,
7

Proces może przesłuchać system plików w celu ustalenia jego bieżącego katalogu roboczego, używając metody, która jest zbyt skomplikowana, aby być na ten temat jako odpowiedź na to pytanie. To właśnie robią pwdprogram i getcwdfunkcja biblioteki. Na początku Uniksa były to jedyne sposoby, aby dowiedzieć się, jaki był twój katalog roboczy. Oto część odpowiedzi na twoje pytanie, której nie mogę znaleźć w żadnej innej odpowiedzi ani w żadnym innym miejscu na tej stronie (po 42 sekundach wyszukiwania):

  • Kiedy powłoka się uruchamia, pobiera bieżący katalog roboczy (prawdopodobnie przez wywołanie getcwd).
  • Następnie, za każdym razem, gdy wykonujesz a cd, pushdlub popd, powłoka śledzi katalog roboczy za pomocą funkcji manipulacji ciągami. Na przykład,

    • Jeśli twój katalog roboczy jest /home/simi ty wpiszesz cd .., powłoka obliczy, że katalogiem roboczym jest /home.
    • Jeśli twój katalog roboczy jest /home/simi ty wpiszesz cd ., powłoka obliczy, że twój katalog roboczy jest nadal /home/sim.
    • Jeśli twój katalog roboczy jest /home/simi wpiszesz cd aa, powłoka obliczy, że katalog roboczy jest /home/sim/aa- bez sprawdzania, czy aajest dowiązaniem symbolicznym.

    Robi to, aby zaoszczędzić na „kosztach” połączeń getcwd. Jest to jednak kompromis, ponieważ może prowadzić do niepoprawnych informacji.

  • Polecenie pwd(wbudowane) wyświetla po prostu zapamiętane / obliczone przez powłokę pojęcie katalogu roboczego.
  • Ponadto powłoka umieszcza zapamiętane / obliczone pojęcie katalogu roboczego w zmiennej środowiskowej PWD, dla wygody procesów użytkownika. Proces nigdy nie powinien na tym polegać, jeśli potrzebuje dokładnych informacji.

Najważniejsze jest to, że powłoka może się mylić, gdzie się znajduje. Ale jeśli wpiszesz /bin/pwd, uruchomi się to w osobnym procesie, który nie ma dostępu do pojęcia powłoki o tym, czym jest katalog roboczy, a więc określa prawdziwy katalog roboczy w staromodny sposób. (Wyjątek: /bin/pwdprogram może spojrzeć na zmienną środowiskową PWD i najwyraźniej robi to po określeniu -L.) Oto inny przykład tego, jak powłoka może się mylić:

cd /home/sim/aa # Załóżmy, że /home, /home/simi /home/sim/aa
# wszystkie są prawdziwymi katalogami (nie symbolicznymi linkami).
pwd # Dane wyjściowe:, /home/sim/aaktóre są poprawne.
mv ../aa ../bb
pwd # Dane wyjściowe:, /home/sim/aaco jest niepoprawne.
/bin/pwd # Dane wyjściowe:, /home/sim/bbktóre są poprawne.


I tylko w przypadku, gdy nie jesteśmy pewni na to, jeśli wpiszesz ln -s . aai cd aa, wówczas aktualny katalog roboczy nie zmieniła , nie bardziej niż to robi po wpisaniu cd .- dlatego, że to, co robisz, gdy wpiszesz w istocie cd aa.

Scott
źródło
Dzięki, bardzo dobra odpowiedź, na to czekałem;)
użytkownik3581976,
2
Ta odpowiedź wydaje się nieco wygięta . Jest coś więcej -Lniż oszczędność kosztów - i $PWDjest zdefiniowana przez użytkownika zmienna środowiskowa określona przez POSIX - aplikacje w przestrzeni użytkownika prawdopodobnie powinny jej ufać (cokolwiek to znaczy ...?) . W każdym razie, chociaż wcale nie jestem fanem dowiązań symbolicznych, to do użytkownika należy pośrednictwo w tak wielu zwariowanych kierunkach, jakie on lub ona powinna z nimi wybrać - i to -Ljest najważniejsze .
mikeserv
1
To powinna być zaakceptowana odpowiedź (dowiązania symboliczne nie są sednem pytania).
Thomas Dickey,