Apa itu ~ (tilde) ketika digunakan sebagai awalan untuk sebuah path?


11

Sunting: Ini adalah duplikat dari /programming/998626/meaning-of-tilde-in-linux-bash-not-home-directory/ . Saya tidak memiliki reputasi untuk menutup pertanyaan ini sebagai duplikat.

Saya tidak merujuk ~seperti pada direktori home melainkan ini:

$ ls ~foo/bar
/some/mount/point/foo/bar

Namun jika saya mencoba dengan titik pemasangan yang berbeda, misalnya:

$ mount | ag "/dev "
devfs on /dev (devfs, local, nobrowse)
$ ls /dev/stdin
/dev/stdin
$ ls ~stdin
zsh: no such user or named directory: stdin . 
# bash has a similar error message: 
ls: ~stdin: No such file or directory

Apa yang ~disebut dalam konteks ini? Bagaimana cara kerjanya?

Sunting: Informasi lebih lanjut berdasarkan beberapa komentar di bawah:

  1. Saya dapat membuktikan bahwa fooitu bukan nama pengguna di sistem saya.
  2. Ketika mencoba untuk melengkapi otomatis, ls -lah ~tidak semua opsi ditampilkan. yaitu saya bisa cd ~qux, ketika quxtidak muncul di autocomplete. Sekali lagi quxbukan pengguna di sistem saya.
  3. Jika yang penting /some/mount/pointadalah berbagi jaringan.
  4. Semua perinciannya menyarankan beberapa nama path muckery, fitur shell Z dari perluasan pathname, tetapi ini juga bekerja di bash, yang tampaknya tidak mendukung hal-hal seperti path bernama shell Z.

5
~fooadalah direktori home pengguna foo. Jika pengguna tidak ditentukan, pengguna saat ini adalah default.
DopeGhoti

Tetapi dalam kasus ini, /some/mount/pointjelas bukan direktori home saya. cd ~membawaku ke /Users/$username/- pertandingan yang mana$HOME
RD

1
zshTampaknya juga menggunakan tilde untuk menunjukkan direktori bernama.
DopeGhoti

Aku juga curiga !! Kecuali untuk beberapa alasan, serangkaian perintah yang saya posting di atas juga berfungsi di bash ( bash -c "ls ~foo/bar") - yang tidak memiliki nama direktori. Lebih jauh lagi bahkan di dalam zsh, jika saya memeriksanya env, saya tidak melihat direktori bernama apa pun disiapkan. Saya menggunakan Mac OS dan saya merasa ini adalah beberapa fitur khusus untuk OS X.
RD

1
Anda hanya berkata ~foo. Ambil string yang sebenarnya (bukan contoh foo) dan lakukan grep "actual username" /etc/passwd. ~textharus bekerja hanya untuk nama pengguna login yang mungkin sesuai dengan manual bash (tidak selalu berarti ia benar-benar dapat login; dalam kasus pengguna sistem seperti ~lp, misalnya). Dalam semua pengujian saya, ~stringberkorespondensi dengan stringmenjadi nama pengguna.
Sergiy Kolodyazhnyy

Jawaban:


14

Apa itu ~ foo

Kutipan dari bash manual (dengan penekanan tambahan):

Jika sebuah kata dimulai dengan karakter tilde tanpa tanda kutip (`~ '), semua karakter sebelum slash tanpa tanda kutip pertama (atau semua karakter, jika tidak ada slash tanpa tanda kutip) dianggap sebagai awalan tilde. Jika tidak ada karakter dalam tilde-prefix dikutip, karakter dalam tilde-prefix setelah tilde diperlakukan sebagai nama login yang memungkinkan .

~foo memperluas ke foodirektori home pengguna persis seperti yang ditentukan dalam /etc/passwd. Perhatikan, bahwa ini dapat mencakup nama pengguna sistem; itu tidak berarti pengguna manusia atau mereka benar-benar dapat masuk secara lokal (mereka dapat masuk melalui kunci SSH misalnya).

Bahkan, seperti disebutkan dalam komentar , bashakan menggunakan getpwnamfungsi. Fungsi itu sendiri ditentukan oleh POSIX standar, maka harus ada pada kebanyakan Unix-seperti sistem, termasuk MacOS X . Fungsi ini tidak terbatas /etc/passwdhanya untuk dan mencari basis data lain, seperti LDAP dan NIS. Kutipan khusus dari bash kode sumber , tilde.cfile, mulai dari baris 394:

  /* No preexpansion hook, or the preexpansion hook failed.  Look in the
     password database. */
  dirname = (char *)NULL;
#if defined (HAVE_GETPWNAM)
  user_entry = getpwnam (username);
#else
  user_entry = 0;

Contoh praktis

Di bawah ini Anda dapat melihat tes dengan nama pengguna sistem di sistem saya. Perhatikan passwdentri dan hasil yang sesuails ~username

$ grep '_apt' /etc/passwd
_apt:x:104:65534::/nonexistent:/bin/false
$ ls ~_apt
ls: cannot access '/nonexistent': No such file or directory
$ grep '^lp' /etc/passwd
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
$ ls ~lp
ls: cannot access '/var/spool/lpd': No such file or directory

Sekalipun misalnya _aptakun dikunci seperti yang disarankan oleh outputnya passwd -S apttetap muncul sebagai nama login yang mungkin:

_apt L 11/29/2017 0 99999 7 -1

Harap dicatat: Ini bukan fitur khusus macOS, melainkan fitur khusus shell.


Saya ragu shell dapat mengandalkan mencari tahu tentang tanggal kedaluwarsa akun atau jika terkunci atau apa pun saat memperluas tilde. Misalnya di Linux, tanggal kedaluwarsa disimpan /etc/shadow, bersama dengan informasi otentikasi lainnya yang dilindungi, seperti kata sandi. Referensi dalam passwdhanya tentang membuat kata sandi tidak valid: itu tidak akan mencegah otentikasi melalui cara lain.
ilkkachu

@ilkkachu Ya, Anda benar. Saya telah mengujinya dengan menambahkan testuserdan memodifikasi tanggal kedaluwarsa kata sandi. Nama pengguna masih muncul dalam penyelesaian tab. Saya telah menghapus sedikit itu dari jawabannya
Sergiy Kolodyazhnyy

1
Satu-satunya masalah dengan jawaban ini adalah bahwa ia mengutip bashhalaman manual (dan sepertinya yang lama). OP sebenarnya menggunakan zsh(bisa lebih jelas), meskipun dalam komentar disebutkan bashmemiliki perilaku yang sama.
Ken Wayne VanderLinde

2
Anda bisa menggunakan getent passwd foodaripada grep foo /etc/passwordmengikuti mekanisme pencarian yang sama seperti shell - mungkin termasuk layanan direktori berbasis jaringan yang @Abigail sebutkan.
RJHunter

1
Diterima sebagai jawaban untuk bit 'seperti LDAP dan NIS', yang ternyata benar dalam kasus saya!
RD

5

Singkatnya mengapa Anda melihat sesuatu ~foo/bar, itu karena Anda memiliki nama pengguna foopada sistem dengan folder bernama bardi direktori home mereka.

Lihat solusi ini di komunitas lain yang menjelaskan mengapa (tilde) ~lebih dari sekadar "direktori home".

Jika Anda memiliki nama pengguna bindi sistem Anda, maka Anda bisa mendaftar isi direktori home bin dengan perintah:

ls ~bin

Satu hal lain yang dapat Anda coba adalah menggunakan tab completion setelah mengetik berikut pada prompt (jangan carriage return, cukup gunakan tombol tab):

ls -lah ~ tab

untuk melihat daftar direktori home pengguna yang ~akan diperluas ke jika Anda terus. Contoh (terpotong) output dari penyelesaian tabls -lah ~ tab

$ ls -lah ~ [tab]
~antman/            ~games/
~bin/               ~mail/

1
+1 untuk penyelesaian tab. Ini dengan jelas mengungkapkan semua nama pengguna yang dapat diperoleh bash dari nama login yang mungkin /etc/passwd. Segera membantu untuk memperjelas apa yang terjadi jika pengguna tentu saja mengetahui nama pengguna yang mereka miliki di sistem.
Sergiy Kolodyazhnyy

2
Terima kasih atas tip tentang penyelesaian bash - menghasilkan beberapa hasil autocomplete yang menarik. Saat ~foomelakukan pelengkapan otomatis, saya dapat membuktikan bahwa foobukan pengguna di sistem saya (dan memang tidak ada di /etc/passwd). Selanjutnya, semua folder / file di /some/mount/pointtampilkan di autocomplete yang super menarik.
RD
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.