ในกรณีที่พบบ่อยที่สุด$0จะมีเส้นทางแน่นอนหรือสัมพันธ์กับสคริปต์ดังนั้น
script_path=$(readlink -e -- "$0")
(สมมติว่ามีreadlinkคำสั่งและสนับสนุน-e) โดยทั่วไปเป็นวิธีที่ดีพอที่จะรับเส้นทางสัมบูรณ์ซึ่งเป็นที่ยอมรับไปยังสคริปต์
$0 ถูกกำหนดจากอาร์กิวเมนต์ที่ระบุสคริปต์ตามที่ส่งไปยังล่าม
ตัวอย่างเช่นใน:
the-shell -shell-options the/script its args
$0the/scriptได้รับ
เมื่อคุณทำงาน:
the/script its args
เปลือกของคุณจะทำ:
exec("the/script", ["the/script", "its", "args"])
หากสคริปต์มีตัวอย่าง#! /bin/sh -บางอย่างระบบจะแปลงให้เป็น:
exec("/bin/sh", ["/bin/sh" or "the/script", "-", "the/script", "its", "args"])
(ถ้ามันไม่มี she-bang หรือมากกว่านั้นโดยทั่วไปถ้าระบบส่งคืนข้อผิดพลาด ENOEXEC ดังนั้นเชลล์ของคุณจะทำสิ่งเดียวกัน)
มีข้อยกเว้นสำหรับสคริปต์ setuid / setgid ในบางระบบที่ระบบจะเปิดสคริปต์ในบางfd xและเรียกใช้แทน:
exec("/bin/sh", ["/bin/sh" or "the/script", "-", "/dev/fd/x", "its", "args"])
เพื่อหลีกเลี่ยงสภาพการแข่งขัน (ในกรณีนี้$0จะมี/dev/fd/x)
ตอนนี้คุณอาจยืนยันว่า/dev/fd/x เป็นเส้นทางไปยังสคริปต์นั้น อย่างไรก็ตามโปรดทราบว่าถ้าคุณอ่านจาก$0คุณจะทำลายสคริปต์ในขณะที่คุณใช้การป้อนข้อมูล
ตอนนี้มีความแตกต่างถ้าชื่อคำสั่งสคริปต์ตามที่เรียกใช้ไม่ได้มีเครื่องหมายทับ ใน:
the-script its args
เปลือกของคุณจะมีลักษณะขึ้นในthe-script อาจมีพา ธ สัมบูรณ์หรือสัมพัทธ์ (รวมถึงสตริงว่าง) ไปยังบางไดเรกทอรี ตัวอย่างเช่นหากมีและพบได้ในไดเรกทอรีปัจจุบันเปลือกจะทำ:$PATH$PATH$PATH/bin:/usr/bin:the-script
exec("the-script", ["the-script", "its", "args"])
ซึ่งจะกลายเป็น:
exec("/bin/sh", ["/bin/sh" or "the-script", "-", "the-script", "its", "args"]
หรือหากพบใน/usr/bin:
exec("/usr/bin/the-script", ["the-script", "its", "args"])
exec("/bin/sh", ["/bin/sh" or "the-script" or "/usr/bin/the-script",
"-", "/usr/bin/the-script", "its", "args")
ในทุกกรณีข้างต้นยกเว้นกรณีมุม setuid $0จะมีเส้นทาง (สัมบูรณ์หรือญาติ) ไปยังสคริปต์
ตอนนี้สคริปต์สามารถถูกเรียกเป็น:
the-interpreter the-script its args
เมื่อthe-scriptดังกล่าวข้างต้นไม่มีอักขระทับ, พฤติกรรมแตกต่างกันเล็กน้อยจากเปลือกหอยเพื่อเปลือก
การใช้งาน AT&T แบบเก่าkshนั้นค้นหาสคริปต์โดยไม่มีเงื่อนไข$PATH(ซึ่งจริงๆแล้วเป็นข้อผิดพลาดและช่องโหว่ด้านความปลอดภัยสำหรับสคริปต์ setuid) ดังนั้น$0จริง ๆ แล้วไม่ได้มีเส้นทางไปยังสคริปต์เว้นแต่การ$PATHค้นหาจะเกิดขึ้นจริงthe-scriptในไดเรกทอรีปัจจุบัน
ใหม่กว่า AT&T kshจะพยายามตีความthe-scriptในไดเรกทอรีปัจจุบันหากสามารถอ่านได้ ถ้าไม่ได้ก็จะค้นหาสำหรับอ่านและปฏิบัติการ ในthe-script$PATH
สำหรับbashมันตรวจสอบว่าthe-scriptอยู่ในไดเรกทอรีปัจจุบัน (และไม่ได้เป็น symlink หัก) และหากไม่ได้ค้นหาหาอ่านได้ (ไม่จำเป็นต้องปฏิบัติการ) ในthe-script$PATH
zshในการshจำลองจะทำbashยกเว้นว่าถ้าthe-scriptเป็น symlink ที่ขาดในไดเรกทอรีปัจจุบันมันจะไม่ค้นหาthe-scriptใน$PATHและจะรายงานข้อผิดพลาดแทน
อื่น ๆ ทั้งหมดที่บอร์นเหมือนเปลือกหอยไม่ได้ดูในthe-script$PATH
สำหรับเชลล์เหล่านั้นถ้าคุณพบว่า$0มันไม่มี/และไม่สามารถอ่านได้มันก็อาจจะถูก$PATHค้นหา จากนั้นเป็นไฟล์ใน$PATHมีแนวโน้มที่จะปฏิบัติการได้ก็อาจจะประมาณปลอดภัยที่จะใช้command -v -- "$0"ในการค้นหาเส้นทางของมัน ( แต่ที่จะไม่ทำงานถ้า$0เกิดขึ้นยังเป็นชื่อของ builtin เปลือกหรือคำหลัก (ในเปลือกหอยมากที่สุด))
ดังนั้นหากคุณต้องการที่จะครอบคลุมสำหรับกรณีที่คุณสามารถเขียนมัน:
progname=$0
[ -r "$progname" ] || progname=$(
IFS=:; set -f
for i in ${PATH-$(getconf PATH)}""; do
case $i in
"") p=$progname;;
*/) p=$i$progname;;
*) p=$i/$progname
esac
[ -r "$p" ] && exec printf '%s\n' "$p"
done
exit 1
) && progname=$(readlink -e -- "$progname") ||
progname=unknown
(สิ่งที่""แนบมา$PATHคือเพื่อรักษาองค์ประกอบว่างท้ายด้วยเปลือกหอยซึ่ง$IFSทำหน้าที่เป็นตัวคั่นแทนตัวคั่น )
ตอนนี้มีวิธีที่ลึกลับมากกว่าในการเรียกใช้สคริปต์ เราสามารถทำได้:
the-shell < the-script
หรือ:
cat the-script | the-shell
ในกรณีนั้น$0จะเป็นอาร์กิวเมนต์แรก ( argv[0]) ที่ล่ามได้รับ (ด้านบนthe-shellแต่อาจเป็นอะไรก็ได้โดยทั่วไปแล้วทั้งชื่อฐานหรือเส้นทางเดียวกับล่ามนั้น)
การตรวจจับว่าคุณอยู่ในสถานการณ์นั้นตามค่าของ$0ไม่น่าเชื่อถือ คุณสามารถดูผลลัพธ์ของps -o args= -p "$$"การรับเบาะแส ในกรณีไปป์ไม่มีทางจริงที่คุณสามารถกลับไปที่เส้นทางไปยังสคริปต์ได้
เราสามารถทำได้เช่นกัน:
the-shell -c '. the-script' blah blih
แล้วยกเว้นในzsh(และบางการดำเนินงานเก่าของเปลือกบอร์น) จะเป็น$0 blahอีกครั้งยากที่จะได้รับเส้นทางของสคริปต์ในเปลือกเหล่านั้น
หรือ:
the-shell -c "$(cat the-script)" blah blih
เป็นต้น
เพื่อให้แน่ใจว่าคุณมีสิทธิ์$prognameคุณสามารถค้นหาสตริงที่ต้องการใน:
progname=$0
[ -r "$progname" ] || progname=$(
IFS=:; set -f
for i in ${PATH-$(getconf PATH)}:; do
case $i in
"") p=$progname;;
*/) p=$i$progname;;
*) p=$i/$progname
esac
[ -r "$p" ] && exec printf '%s\n' "$p"
done
exit 1
) && progname=$(readlink -e -- "$progname") ||
progname=unknown
[ -f "$progname" ] && grep -q 7YQLVVD3UIUDTA32LSE8U9UOHH < "$progname" ||
progname=unknown
แต่อีกครั้งฉันไม่คิดว่ามันคุ้มค่ากับความพยายาม
$0มีบางอย่างที่ไม่ใช่สคริปต์ซึ่งจะตอบคำถามชื่อ อย่างไรก็ตามฉันยังสนใจในสถานการณ์ที่$0ตัวของสคริปต์เอง แต่ไม่รวมไดเรกทอรี โดยเฉพาะฉันพยายามเข้าใจความคิดเห็นที่ทำไว้ในคำตอบ SO