Perbedaan aneh antara pwd dan / bin / pwd

15

Saya menambahkan symlink ke direktori saat ini dengan ln -s . aa. Jika saya mengeksekusi cd aa, dan setelah itu saya dieksekusi pwd, jawabannya adalah /home/sim/aa.

Tetapi jika saya mengeksekusinya /bin/pwdmencetak /home/sim(direktori saat ini tidak berubah).

Dari mana perbedaan ini berasal?

pengguna3581976
sumber

Jawaban:

17

Di sebagian besar shell termasuk bash, pwdadalah shell builtin:

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

Jika Anda menggunakan /bin/pwd, Anda harus menggunakan -Lopsi untuk mendapatkan hasil yang sama dengan builtin pwd:

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

Secara default, /bin/pwdabaikan symlink dan cetak direktori yang sebenarnya.

Dari 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.

Built-in pwdtermasuk symlink secara default, kecuali -Popsi itu digunakan, atau -o physicalset builtin diaktifkan.

Dari 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
sumber
Saya tidak yakin untuk memahami dari mana perbedaan itu berasal
user3581976
/bin/pwdabaikan symlink secara default, baca bagian info pwddalam jawaban saya: Cetak nama yang sepenuhnya diselesaikan untuk direktori saat ini. Artinya, semua komponen dari nama yang dicetak akan menjadi nama direktori aktual - tidak ada yang akan menjadi tautan simbolik.
cuonglm
@ user3581976: Lihat pembaruan saya untuk lebih jelas.
cuonglm
Mengapa ada perintah -L untuk pwd meskipun diatur secara default? Dan bukankah shell menggunakan perintah / bin / pwd untuk menjalankan pwd?
user3581976
2
@ user3581976: Gambar yang Anda mulai dengan shell Anda set -o physical, sekarang pwdadalah -Popsi gunakan secara default, jika Anda tidak memiliki -Lpilihan, bagaimana Anda mencetak jalan berisi symlink? Baca ini https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.htmluntuk mengetahui apa set -o physicalfungsinya.
cuonglm
7

Dimungkinkan untuk proses menginterogasi sistem file untuk menentukan direktori kerjanya saat ini, menggunakan metode yang sedikit terlalu rumit untuk menjadi topik sebagai jawaban untuk pertanyaan ini. Inilah yangpwd program dan getcwdperpustakaan. Pada masa-masa awal Unix, mereka adalah satu-satunya cara untuk mengetahui direktori kerja Anda. Inilah bagian dari jawaban untuk pertanyaan Anda yang tidak dapat saya temukan di jawaban lain mana pun, atau bahkan di mana pun di situs ini (setelah pencarian 42 detik):

  • Ketika shell mulai, ia mendapat direktori kerjanya saat ini (mungkin dengan memanggil getcwd ).
  • Setelah itu, setiap kali Anda melakukan cd, pushdataupopd , shell melacak dari direktori kerja menggunakan fungsi manipulasi string. Sebagai contoh,

    • Jika direktori kerja /home/simAnda dan Anda mengetik cd .., shell menghitung bahwa direktori kerja Anda /home.
    • Jika direktori kerja /home/simAnda dan Anda mengetik cd ., shell menghitung bahwa direktori kerja Anda masih /home/sim.
    • Jika direktori kerja /home/simAnda dan Anda mengetik cd aa, shell menghitung bahwa direktori kerja Anda /home/sim/aa- tanpa memeriksa untuk melihat apakah aatautan simbolik.

    Ini melakukan ini untuk menghemat "biaya" panggilan getcwd. Tetapi ini adalah kompromi, karena dapat menghasilkan informasi yang salah.

  • Perintah pwd(builtin) hanya menampilkan gagasan diingat / dikomputasi shell tentang apa direktori kerja.
  • Juga, shell menempatkan gagasan yang diingat / dihitung tentang apa direktori kerja ke dalam variabel lingkungan PWD, untuk kenyamanan proses pengguna. Suatu proses tidak boleh bergantung pada ini jika menginginkan informasi yang akurat.

Jadi, intinya adalah bahwa shell bisa bingung di mana itu. Tetapi jika Anda mengetik /bin/pwd, itu berjalan dalam proses terpisah yang tidak memiliki akses ke gagasan shell tentang apa direktori yang berfungsi, dan itu menentukan direktori kerja yang benar itu sendiri, cara kuno. (Pengecualian: /bin/pwdprogram dapat melihat variabel lingkungan PWD, dan ternyata itu berfungsi saat Anda menentukan -L.) Berikut adalah contoh lain bagaimana shell bisa membingungkan:

cd /home/sim/aa # Asumsikan bahwa /home,, /home/simdan /home/sim/aa
# semua direktori nyata (bukan tautan simbolik).
pwd # Output:, /home/sim/aayang benar.
mv ../aa ../bb
pwd # Output:, /home/sim/aayang tidak benar.
/bin/pwd # Output:, /home/sim/bbyang benar.


Dan, kalau-kalau Anda tidak jelas tentang ini, jika Anda mengetik ln -s . aadan cd aa, maka direktori kerja Anda saat ini tidak berubah , tidak seperti ketika Anda mengetik cd .- karena, pada dasarnya itulah yang Anda lakukan saat mengetik cd aa.

Scott
sumber
Terima kasih, jawaban yang sangat bagus, ini yang saya tunggu;)
user3581976
2
Jawaban ini sepertinya sedikit bengkok . Ada lebih -Ldari menghemat biaya - dan $PWDmerupakan variabel lingkungan yang ditentukan POSIX yang ditentukan pengguna - aplikasi ruang pengguna mungkin harus mempercayainya (apa pun artinya ...?) . Ngomong-ngomong, sementara saya sama sekali bukan penggemar symlink, itu adalah hak prerogatif pengguna untuk secara tidak langsung ke arah gila sebanyak yang harus dia pilih dengan mereka - dan itulah yang -Llebih penting daripada apa pun.
mikeserv
1
Ini harus menjadi jawaban yang diterima (tautan simbolik bukan titik pertanyaan).
Thomas Dickey