~ (tilde) คืออะไรเมื่อใช้เป็นคำนำหน้าไปยังเส้นทาง


11

แก้ไข: นี่คือซ้ำ/programming/998626/meaning-of-tilde-in-linux-bash-not-home-directory/ ฉันไม่มีชื่อเสียงที่จะปิดคำถามนี้ซ้ำ

ฉันไม่ได้อ้างถึง~ในไดเรกทอรีบ้าน แต่สิ่งนี้:

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

อย่างไรก็ตามหากฉันลองด้วยจุดเมานต์ที่แตกต่างกันเช่น:

$ 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

สิ่งที่~เรียกว่าในบริบทนี้? มันทำงานยังไง?

แก้ไข: ข้อมูลเพิ่มเติมจากความคิดเห็นบางส่วนด้านล่าง:

  1. ฉันสามารถยืนยันได้ว่าfooไม่ใช่ชื่อผู้ใช้ในระบบของฉัน
  2. เมื่อพยายามเติมข้อความอัตโนมัติระบบจะls -lah ~ไม่แสดงตัวเลือกทั้งหมด เช่นฉันสามารถcd ~quxเมื่อquxไม่แสดงในการเติมข้อความอัตโนมัติ อีกครั้งquxไม่ใช่ผู้ใช้ในระบบของฉัน
  3. หากเป็นเรื่อง/some/mount/pointเครือข่ายร่วมกัน
  4. รายละเอียดทั้งหมดแนะนำให้พา ธ ที่สร้างชื่อไว้ซึ่งเป็นคุณลักษณะของเชลล์ Z ของการขยายชื่อพา ธ แต่วิธีนี้จะทำงานได้ดีเช่นกันซึ่งดูเหมือนจะไม่สนับสนุนสิ่งต่าง ๆ เช่นพา ธ ที่มีชื่อของเชลล์ Z

5
~foofooเป็นไดเรกทอรีบ้านของผู้ใช้ หากไม่ได้ระบุผู้ใช้ผู้ใช้ปัจจุบันจะเป็นค่าเริ่มต้น
DopeGhoti

แต่ในกรณีนี้/some/mount/pointแน่นอนไม่ใช่ไดเรกทอรีบ้านของฉัน cd ~พาฉันไปที่/Users/$username/$HOME
RD

1
zshดูเหมือนว่าจะใช้เครื่องหมายตัวหนอนเพื่อระบุไดเรกทอรีที่มีชื่อ
DopeGhoti

ฉันก็สงสัยเช่นกัน !! ยกเว้นด้วยเหตุผลบางอย่างชุดคำสั่งที่ฉันโพสต์ข้างต้นทำงานในทุบตีเช่นกัน ( bash -c "ls ~foo/bar") - ซึ่งไม่ได้มีชื่อไดเรกทอรี ยิ่งไปกว่านั้นภายใน zsh หากฉันตรวจสอบenvฉันไม่เห็นไดเรกทอรีที่ตั้งชื่อใด ๆ ฉันใช้ Mac OS และฉันรู้สึกว่านี่เป็นคุณสมบัติเฉพาะของ OS X
RD

1
~fooคุณกล่าวว่า ใช้สตริงจริง (ไม่ได้ตัวอย่างfoo) grep "actual username" /etc/passwdและทำ ~textควรทำงานกับชื่อผู้ใช้ที่เป็นไปได้เท่านั้นตามคู่มือ bash (ไม่ได้แปลว่ามันสามารถเข้าสู่ระบบได้จริงในกรณีของผู้ใช้ระบบเช่น~lpเช่น) ในการทดสอบทั้งหมดของฉันนั้น~stringสอดคล้องกับstringการเป็นชื่อผู้ใช้
Sergiy Kolodyazhnyy

คำตอบ:


14

~ foo คืออะไร

อ้างอิงจากbash manual (พร้อมเน้นเพิ่ม):

หากคำขึ้นต้นด้วยอักขระ tilde ที่ไม่มีเครื่องหมาย (`~ ') อักขระทั้งหมดที่อยู่ก่อนเครื่องหมายทับแรก (หรืออักขระทั้งหมดหากไม่มีเครื่องหมายทับที่ไม่มีเครื่องหมายอัญประกาศ) ถือว่าเป็นคำนำหน้าตัวหนอนหากไม่มีอักขระใน tilde-prefix ถูกอ้างถึงอักขระใน tilde-prefix หลังจาก tilde ถูกใช้เป็นชื่อล็อกอินที่เป็นไปได้

~foo ขยายไปยังไดเรกทอรีบ้านของผู้ใช้ตรงตามที่ระบุไว้ในfoo /etc/passwdโปรดทราบว่าสิ่งนี้อาจรวมถึงชื่อผู้ใช้ของระบบ มันไม่ได้แปลว่าผู้ใช้ที่เป็นมนุษย์หรือว่าพวกเขาสามารถเข้าสู่ระบบได้ในท้องถิ่น

ในความเป็นจริงตามที่ระบุไว้ในการแสดงความคิดเห็น , bashจะใช้getpwnamฟังก์ชั่น ฟังก์ชั่นที่ตัวเองจะถูกระบุโดยPOSIXมาตรฐานจึงควรมีอยู่ในส่วน Unix เหมือนระบบรวมทั้งMacOS X ฟังก์ชันนี้ไม่ได้ จำกัด อยู่/etc/passwdเพียงค้นหาฐานข้อมูลอื่นเช่น LDAP และ NIS ตัดตอนมาโดยเฉพาะอย่างยิ่งจากbash รหัสที่มา , tilde.cไฟล์เริ่มต้นที่ 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;

ตัวอย่างการปฏิบัติ

ด้านล่างคุณสามารถดูการทดสอบด้วยชื่อผู้ใช้ระบบในระบบของฉัน ให้ความสนใจกับpasswdรายการที่เกี่ยวข้องและผลลัพธ์ของls ~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

แม้ว่า_aptบัญชีอินสแตนซ์จะถูกล็อคตามที่แนะนำโดยเอาท์พุทของpasswd -S aptมันยังคงปรากฏเป็นชื่อเข้าสู่ระบบที่เป็นไปได้

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

โปรดทราบ:นี่ไม่ใช่คุณสมบัติเฉพาะของ macOS แต่เป็นคุณลักษณะเฉพาะของเชลล์


ฉันสงสัยว่าเชลล์สามารถพึ่งพาการค้นหาสิ่งใดเกี่ยวกับวันหมดอายุของบัญชีหรือถ้ามันถูกล็อกหรืออะไรก็ตามเมื่อขยายตัวหนอน เช่นบน Linux วันหมดอายุจะถูกเก็บไว้/etc/shadowพร้อมกับข้อมูลการตรวจสอบความถูกต้องอื่น ๆ เช่นรหัสผ่าน การอ้างอิงในpasswdนั้นเกี่ยวกับการทำให้รหัสผ่านไม่ถูกต้อง: ซึ่งจะไม่ป้องกันการตรวจสอบสิทธิ์ด้วยวิธีการอื่น
ilkkachu

@ilkkachu ใช่คุณพูดถูก ฉันทดสอบด้วยการเพิ่มtestuserและแก้ไขวันหมดอายุของรหัสผ่าน ชื่อผู้ใช้ยังคงปรากฏในแท็บเสร็จสมบูรณ์ ฉันลบบิตนั้นออกจากคำตอบแล้ว
Sergiy Kolodyazhnyy

1
ปัญหาเดียวของคำตอบนี้คือมันเป็นการอ้างอิงคำสั่งbashman page (และอันเก่าที่มันดูเหมือน) OP ใช้งานจริงzsh(อาจชัดเจนกว่า) แม้ว่าในความคิดเห็นจะกล่าวถึงว่าbashมีพฤติกรรมเหมือนกัน
Ken Wayne VanderLinde

2
คุณสามารถใช้getent passwd fooแทนที่จะgrep foo /etc/passwordทำตามกลไกการค้นหาเดียวกับเชลล์ - อาจรวมถึงบริการไดเรกทอรีบนเครือข่ายที่ @Abigail กล่าวถึง
RJHunter

1
ยอมรับว่าเป็นคำตอบสำหรับบิต 'เช่น LDAP และ NIS' ซึ่งสิ้นสุดลงถูกต้องในกรณีของฉัน!
RD

5

โดยสรุปว่าทำไมคุณถึงเห็นบางสิ่งบางอย่าง~foo/barมันเป็นเพราะคุณมีผู้ใช้ชื่อfooในระบบที่มีชื่อโฟลเดอร์barในไดเรกทอรีบ้านของพวกเขา

ดูโซลูชันนี้ในชุมชนอื่นที่อธิบายว่าทำไม (tilde) ~เป็นมากกว่า "โฮมไดเร็กตอรี่"

หากคุณมีชื่อผู้ใช้binในระบบของคุณคุณสามารถแสดงรายการเนื้อหาของโฮมไดเร็กทอรีของbinโดยคำสั่ง:

ls ~bin

อีกสิ่งหนึ่งที่คุณสามารถลองใช้ได้ก็คือการใช้แท็บเสร็จสมบูรณ์หลังจากพิมพ์ข้อความต่อไปนี้ที่พรอมต์ (ไม่ต้องปัดแคร่คืนสินค้าเพียงใช้คีย์แท็บ):

ls -lah ~ tab

เพื่อดูรายการไดเรกทอรีบ้านของผู้ใช้ที่~จะขยายไปหากคุณดำเนินการต่อไป ตัวอย่าง (ตัด) เอาท์พุทของความสมบูรณ์ของแท็บls -lah ~ tab

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

1
+1 เมื่อเสร็จสิ้นแท็บ /etc/passwdนี้อย่างชัดเจนเผยชื่อผู้ใช้ทั้งหมดที่ทุบตีจะได้รับชื่อเข้าสู่ระบบเป็นไปได้จาก มันจะช่วยให้ชัดเจนในทันทีว่าเกิดอะไรขึ้นหากผู้ใช้แน่นอนรับรู้ถึงชื่อผู้ใช้ที่พวกเขามีในระบบ
Sergiy Kolodyazhnyy

2
ขอบคุณสำหรับเคล็ดลับในการทุบตีจนเสร็จสมบูรณ์ - ทำให้ได้ผลลัพธ์การเติมข้อความอัตโนมัติที่น่าสนใจ ในขณะที่~fooเติมข้อความอัตโนมัติฉันสามารถยืนยันได้ว่าfooไม่ใช่ผู้ใช้ในระบบของฉัน (และไม่มีอยู่จริง/etc/passwd) นอกจากนี้โฟลเดอร์ / ไฟล์ทั้งหมดที่/some/mount/pointแสดงในการเติมข้อความอัตโนมัติที่น่าสนใจมาก
RD
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.