ในกรณีที่พบบ่อยที่สุด$0
จะมีเส้นทางแน่นอนหรือสัมพันธ์กับสคริปต์ดังนั้น
script_path=$(readlink -e -- "$0")
(สมมติว่ามีreadlink
คำสั่งและสนับสนุน-e
) โดยทั่วไปเป็นวิธีที่ดีพอที่จะรับเส้นทางสัมบูรณ์ซึ่งเป็นที่ยอมรับไปยังสคริปต์
$0
ถูกกำหนดจากอาร์กิวเมนต์ที่ระบุสคริปต์ตามที่ส่งไปยังล่าม
ตัวอย่างเช่นใน:
the-shell -shell-options the/script its args
$0
the/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