เท่ากับ $ HOME เสมอหรือเปล่า


40

ฉันรู้ว่าอาจมีการถามก่อนหน้านี้ แต่ฉันไม่พบมันด้วย Google

ป.ร. ให้ไว้

  • เคอร์เนล Linux
  • ไม่มีการกำหนดค่าที่เปลี่ยนแปลง $ HOME
  • ทุบตี

จะ~ == $HOMEเป็นจริงหรือ


3
ฉันเชื่ออย่างนั้น แต่นี่ไม่ใช่ปัญหาเฉพาะของ Linux ค่อนข้างฉันเชื่อว่า~จะเทียบเท่ากับ$HOMEในสภาพแวดล้อม POSIX ใด ๆ ; แต่ฉันอาจจะผิด
HalosGhost

4
แม้จะมีคำตอบด้านล่าง…ไม่เสมอไป เปรียบเทียบและecho "~" echo "$HOME"
Sparhawk

@Sparhawk เดี๋ยวก่อนดังนั้น 1 + 1 ไม่ใช่ 2? มันเป็นแผนการ! รัฐบาลกำลังซ่อนบางสิ่งบางอย่างจากเรา! : P
Doorknob

1
@Sparhawk คุณจะสังเกตเห็น OP จริงไม่พูดอย่างใดอย่างหนึ่งหรือ~ $HOME: P
HalosGhost

2
@ HalosGhost อ่าจุดดี (ต่อมาฉันก็สังเกตเห็นว่าคำตอบของไมเคิลโฮเมอร์กล่าวถึง " คำตอบเดียว~") อย่างไรก็ตามสิ่งที่คุณควรคำนึงถึงสำหรับผู้อ่านทั่วไปเช่นฉัน
Sparhawk

คำตอบ:


46

สิ่งสำคัญที่ต้องเข้าใจคือ~การขยายเป็นคุณลักษณะของเชลล์ (ของเชลล์บางตัว) มันไม่ใช่ตัวอักษรเวทมนต์มากกว่าที่จะหมายถึงโฮมไดเร็กตอรี่ที่คุณใช้

มันถูกขยาย (โดยเชลล์ซึ่งเป็นแอ็พพลิเคชันที่ใช้ตีความบรรทัดคำสั่ง) เช่น$varถูกขยายเป็นค่าภายใต้เงื่อนไขบางอย่างเมื่อใช้ในบรรทัดคำสั่งเชลล์ก่อนที่คำสั่งจะถูกดำเนินการ

คุณสมบัติดังกล่าวปรากฏตัวครั้งแรกใน C-shell ในช่วงปลายทศวรรษ 1970 (บอร์นเชลล์ไม่ได้มีหรือไม่ได้เป็นรุ่นก่อนหน้าของ ธ ​​อมป์สันเชลล์) ถูกเพิ่มเข้ามาใน Korn เชลล์ (เชลล์ใหม่ที่สร้างขึ้นบนเชลล์ Bourne ใน 80) ในที่สุดมันก็มาตรฐานโดย POSIX และตอนนี้ที่มีอยู่ในเปลือกหอยส่วนใหญ่รวมทั้งคนที่ไม่ใช่ POSIX fishเช่น

เนื่องจากมันมีการใช้งานอย่างแพร่หลายในเชลล์แอปพลิเคชันที่ไม่ใช่เชลล์บางตัวจึงรับรู้ได้ว่ามันหมายถึงโฮมไดเร็กตอรี่ นั่นคือกรณีที่มีการใช้งานจำนวนมากในแฟ้มการกำหนดค่าของพวกเขาหรือพวกเขาเองบรรทัดคำสั่ง ( mutt, slrn, vim... )

bashโดยเฉพาะ (ซึ่งเป็นเชลล์ของโครงการ GNU และใช้กันอย่างแพร่หลายในหลายระบบปฏิบัติการบน Linux) เมื่อมีการเรียกใช้shนั้นส่วนใหญ่จะเป็นไปตามกฎ POSIXเกี่ยวกับ~การขยายตัวและในพื้นที่ที่ไม่ได้ระบุไว้โดย POSIX พฤติกรรมส่วนใหญ่จะเหมือนกับ Korn เชลล์ ซึ่งมันเป็นส่วนโคลน)

ขณะที่$varถูกขยายในสถานที่ส่วนใหญ่ (ยกเว้นในเครื่องหมายคำพูดเดียว) ~การขยายการคิดภายหลังจะขยายในเงื่อนไขเฉพาะบางอย่างเท่านั้น

มันจะขยายตัวเมื่ออาร์กิวเมนต์ของตัวเองในรายการบริบทในบริบทที่คาดว่าสตริง

นี่คือตัวอย่างบางส่วนของที่ขยายในbash:

  • cmd arg ~ other arg
  • var=~
  • var=x:~:x(ต้องการโดย POSIX ใช้สำหรับตัวแปรเช่นPATH, MANPATH... )
  • for i in ~
  • [[ ~ = text ]]
  • [[ text = ~ ]](การขยายตัวของ~การถ่ายเป็นรูปแบบใน AT&T kshแต่ไม่ใช่bashตั้งแต่ 4.0)
  • case ~ in ~) ...
  • ${var#~} (แม้ว่าจะไม่ได้อยู่ในกระสุนอื่น ๆ )
  • cmd foo=~(แม้ว่าจะไม่ใช่เมื่อถูกเรียกเป็นshและเฉพาะเมื่อสิ่งที่อยู่ทางด้านซ้ายของ=มีรูปร่างเหมือนbashชื่อตัวแปรที่ไม่ได้กล่าวถึง)
  • cmd ~/x (ต้องการโดย POSIX อย่างเห็นได้ชัด)
  • cmd ~:x(แต่ไม่ใช่x:~:xหรือx-~-x)
  • a[~]=foo; echo "${a[~]} $((a[~]))" (ไม่ได้อยู่ในเปลือกหอยอื่น ๆ )

นี่คือตัวอย่างบางส่วนที่ไม่ได้ขยาย:

  • echo "~" '~'
  • echo ~@ ~~(โปรดทราบว่า~uมีไว้เพื่อขยายไปยังโฮมไดเร็กตอรี่ของผู้ใช้u)
  • echo @~
  • (( HOME == ~ )), $(( var + ~ ))
  • ด้วยextglob: case $var in @(~|other))...(แม้ว่าcase $var in ~|other)จะตกลง)
  • ./configure --prefix=~(เนื่องจาก--prefixไม่ใช่ชื่อตัวแปรที่ถูกต้อง)
  • cmd "foo"=~(ในbashเพราะคำพูด)
  • เมื่อเรียกใช้เป็นsh: export "foo"=~, env JAVA_HOME=~ cmd...

สำหรับสิ่งที่มันขยายเป็น: ~เพียงอย่างเดียวขยายไปยังเนื้อหาของHOMEตัวแปรหรือเมื่อไม่ได้ตั้งค่าไว้ที่โฮมไดเร็กทอรีของผู้ใช้ปัจจุบันในฐานข้อมูลบัญชี (เป็นส่วนขยายเนื่องจาก POSIX ทำให้พฤติกรรมนั้นไม่ได้กำหนดไว้)

ควรสังเกตว่าใน ksh88 และbashเวอร์ชันก่อนหน้า 4.0 การขยายตัวหนอนจะได้รับการทำให้เป็นวงกลม(การสร้างชื่อไฟล์) ในบริบทรายการ:

$ bash -c 'echo "$HOME"'
/home/***stephane***
$ bash -c 'echo ~'
/home/***stephane*** /home/stephane
$ bash -c 'echo "~"'
~

ที่ไม่ควรมีปัญหาในกรณีปกติ

โปรดทราบว่าเนื่องจากมีการขยายคำเตือนเดียวกันจะมีผลกับการขยายรูปแบบอื่น ๆ

cd ~

ไม่ทำงานหาก$HOMEเริ่มต้นด้วย-หรือมี..ส่วนประกอบ ดังนั้นแม้ว่าจะไม่สร้างความแตกต่างใด ๆ เลย แต่การพูดอย่างเคร่งครัดควรเขียนว่า:

cd -P -- ~

หรือแม้กระทั่ง:

case ~ in
  (/*) cd -P ~;;
  (*) d=~; cd -P "./$d";;
esac

(เพื่อครอบคลุมค่าที่$HOMEต้องการ-, +2... ) หรือเพียงแค่:

cd

(ตามที่cdนำคุณไปสู่โฮมไดเร็กตอรี่โดยไม่มีอาร์กิวเมนต์)

กระสุนอื่น ๆ มี~การขยายเพิ่มเติมขั้นสูง ตัวอย่างเช่นในzshเรามี:

  • ~4, ~-, ~-2(ด้วยความสมบูรณ์) ที่ใช้ในการขยายไดเรกทอรีในกองไดเรกทอรีของคุณ (สถานที่ที่คุณเคยcdไปมาก่อน)
  • ไดเรกทอรีแบบไดนามิกชื่อ คุณสามารถกำหนดกลไกของคุณเองเพื่อตัดสินใจว่า~somethingจะขยายตัวอย่างไร

25

ในรุ่นใด ๆ ของทุบตีในระบบใด ๆ ใช่ ~เป็นคำที่ตัวเองถูกกำหนดให้ขยายไปยัง:

ค่าของ $ HOME

ดังนั้นมันจะเหมือนกับสิ่งที่$HOMEอยู่ในเชลล์ปัจจุบันเสมอ มีการขยายตัวหนอนอื่น ๆ อีกหลายอย่างเช่น~userสำหรับuserโฮมไดเร็กตอรี่~ของ, แต่สิ่งที่ไม่ได้กล่าวถึงในตัวมันจะขยายออกไป"$HOME"เสมอ

โปรดทราบว่าพฤติกรรมของ~และ$HOMEสามารถแตกต่างกันได้ในบางกรณี: โดยเฉพาะถ้า$HOMEมีช่องว่าง (หรืออักขระIFSอื่น ๆ) จากนั้น$HOME(ไม่พูดถึง) จะขยายออกเป็นหลายคำในขณะที่~เป็นคำเดียวเสมอ ~ขยายเท่ากับ"$HOME"(ที่ยกมา)

สำหรับคำถามเฉพาะของคุณ:

[[ $HOME == ~ ]]

เป็นจริงเสมอเพราะ[[ ยับยั้งการแยกคำ [[ ~ == $HOME ]อาจจะไม่ได้ถ้าHOMEมีตัวอักษรที่ตรงกับรูปแบบในมัน แต่[[ ~ == "$HOME" ]](เช่นที่ยกมา"$HOME") เป็นจริงเสมอ การใช้ภายในวงเล็บปีกกาเดียวอาจเป็นข้อผิดพลาดทางไวยากรณ์สำหรับค่าของการHOMEเว้นวรรคหรืออักขระพิเศษ สำหรับการกำหนดค่าโฮมไดเรกทอรีที่สมเหตุสมผลใด ๆ~และ"$HOME"เหมือนกันและเปรียบเทียบเท่ากัน


Stéphane Chazelas ได้บันทึกกรณีในความคิดเห็นที่~และ$HOMEให้ค่าที่แตกต่าง: ถ้าคุณunset HOMEแล้วเมื่อคุณใช้~Bash จะโทรgetpwuidเพื่ออ่านค่าออกจากฐานข้อมูลรหัสผ่าน กรณีนี้ไม่รวมอยู่ในเงื่อนไขที่คุณไม่มีการเปลี่ยนแปลงการกำหนดค่า$HOMEแต่ฉันจะพูดถึงเรื่องนี้เพื่อความสมบูรณ์


1
แต่อาจจะไม่ได้/bin/sh bashฉันไม่แน่ใจว่าshข้อมูลจำเพาะของPosix บอกเกี่ยวกับ~
Basile Starynkevitch

1
~ระบุ POSIX ~ไม่ได้อยู่ใน Thomson หรือ Bourne shell (ซึ่งในเวลานั้นมีให้ในรูป/bin/sh) มันไม่ได้อยู่ในrcหรืออนุพันธ์ (ที่จะใช้อย่างอื่น)
Stéphane Chazelas

5
ในเชลล์บางตัวรวมถึงbashหากHOMEไม่ได้ตั้งค่า~จะขยายไปยังโฮมไดเร็กทอรีของผู้ใช้จากฐานข้อมูล passwd เพื่อให้เป็นกรณีที่ไม่อาจขยายไปยังค่าของ~ $HOME
Stéphane Chazelas

1
โปรดทราบว่าbashก่อนที่ bash4 จะใช้ในการทำการวนรอบตามการขยายตัวของตัวหนอน (ลองHOME='/*' bash -c 'echo /*') ดังนั้นHOME=/*; [ "$HOME" = ~ ]จะกลับข้อผิดพลาดที่นั่น
Stéphane Chazelas

4
@cuonglm ฉันตรวจสอบซอร์สโค้ด มันในที่สุด สาย get_current_user_infoซึ่งใช้getpwuidบนแพลตฟอร์มทั้งหมด แต่ Tandem
Michael Homer
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.