Dalam kasus yang paling umum, $0akan berisi path, absolut atau relatif terhadap skrip, jadi
script_path=$(readlink -e -- "$0")
(dengan asumsi ada readlinkperintah dan itu mendukung -e) umumnya adalah cara yang cukup baik untuk mendapatkan path absolut kanonik ke skrip.
$0 ditugaskan dari argumen yang menentukan skrip yang diteruskan ke penerjemah.
Misalnya, di:
the-shell -shell-options the/script its args
$0dapatkan the/script.
Ketika Anda menjalankan:
the/script its args
Shell Anda akan melakukan:
exec("the/script", ["the/script", "its", "args"])
Jika skrip berisi #! /bin/sh -she-bang misalnya, sistem akan mengubahnya menjadi:
exec("/bin/sh", ["/bin/sh" or "the/script", "-", "the/script", "its", "args"])
(jika tidak mengandung she-bang, atau lebih umum lagi jika sistem mengembalikan kesalahan ENOEXEC, maka shell Anda yang akan melakukan hal yang sama)
Ada pengecualian untuk skrip setuid / setgid pada beberapa sistem, di mana sistem akan membuka skrip pada beberapa fd xdan menjalankannya sebagai gantinya:
exec("/bin/sh", ["/bin/sh" or "the/script", "-", "/dev/fd/x", "its", "args"])
untuk menghindari kondisi balapan (dalam hal ini $0akan berisi /dev/fd/x).
Sekarang, Anda mungkin berpendapat bahwa itu /dev/fd/x adalah jalan menuju skrip itu. Namun perhatikan bahwa jika Anda membaca dari $0, Anda akan merusak skrip saat Anda mengkonsumsi input.
Sekarang, ada perbedaan jika nama perintah skrip yang dipanggil tidak mengandung garis miring. Di:
the-script its args
Shell Anda akan mencari the-scriptdi $PATH. $PATHmungkin berisi jalur absolut atau relatif (termasuk string kosong) ke beberapa direktori. Misalnya, jika $PATHberisi /bin:/usr/bin:dan the-scriptditemukan di direktori saat ini, shell akan melakukan:
exec("the-script", ["the-script", "its", "args"])
yang akan menjadi:
exec("/bin/sh", ["/bin/sh" or "the-script", "-", "the-script", "its", "args"]
Atau jika ditemukan di /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")
Dalam semua kasus di atas kecuali kasus sudut setuid, $0akan berisi path (absolut atau relatif) ke skrip.
Sekarang, skrip juga bisa disebut sebagai:
the-interpreter the-script its args
Ketika the-scriptseperti di atas tidak mengandung karakter garis miring, perilaku sedikit berbeda dari shell ke shell.
kshImplementasi AT&T lama benar-benar mencari skrip tanpa syarat di $PATH(yang sebenarnya adalah bug dan lubang keamanan untuk skrip setuid), jadi $0sebenarnya tidak mengandung jalur ke skrip kecuali $PATHpencarian benar-benar ditemukan the-scriptdi direktori saat ini.
AT&T yang lebih baru kshakan mencoba dan menafsirkan the-scriptdalam direktori saat ini jika itu dapat dibaca. Jika tidak akan mencari yang dapat dibaca dan dieksekusi the-script di $PATH.
Karena bash, ia memeriksa apakah the-scriptada di direktori saat ini (dan bukan merupakan symlink yang rusak) dan jika tidak, cari yang dapat dibaca (belum tentu dapat dieksekusi) the-scriptdi $PATH.
zshdalam shemulasi akan melakukan seperti bashkecuali bahwa jika the-scriptsymlink rusak di direktori saat ini, itu tidak akan mencari the-scriptin $PATHdan malah akan melaporkan kesalahan.
Semua kerang mirip Bourne lainnya tidak terlihat the-scriptmasuk $PATH.
Untuk semua kerang itu, jika Anda menemukan yang $0tidak mengandung a /dan tidak dapat dibaca, maka itu mungkin telah dicari $PATH. Kemudian, karena file-file di $PATHdalamnya kemungkinan dapat dieksekusi, mungkin ini perkiraan yang aman untuk digunakan command -v -- "$0"untuk menemukan jalurnya (meskipun itu tidak akan berhasil jika $0kebetulan juga merupakan nama dari shell builtin atau kata kunci (dalam kebanyakan shell)).
Jadi, jika Anda benar-benar ingin menutupi kasus itu, Anda bisa menulisnya:
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
(yang ""ditambahkan $PATHadalah untuk melestarikan elemen kosong yang tertinggal dengan cangkang yang $IFSbertindak sebagai pembatas bukannya pemisah ).
Sekarang, ada lebih banyak cara esoteris untuk menjalankan skrip. Orang bisa melakukan:
the-shell < the-script
Atau:
cat the-script | the-shell
Dalam hal ini, $0akan menjadi argumen pertama ( argv[0]) yang diterima penerjemah (di atas the-shell, tetapi bisa berupa apa saja meskipun umumnya baik nama dasar atau satu jalur ke penerjemah itu).
Mendeteksi bahwa Anda berada dalam situasi itu berdasarkan nilai $0tidak dapat diandalkan. Anda bisa melihat output ps -o args= -p "$$"untuk mendapatkan petunjuk. Dalam kasus pipa, tidak ada cara nyata Anda bisa kembali ke jalur ke skrip.
Orang juga bisa melakukan:
the-shell -c '. the-script' blah blih
Kemudian, kecuali dalam zsh(dan beberapa implementasi lama dari Bourne shell), $0akan blah. Sekali lagi, sulit untuk mendapatkan jalan naskah di shell tersebut.
Atau:
the-shell -c "$(cat the-script)" blah blih
dll.
Untuk memastikan Anda memiliki hak $progname, Anda dapat mencari string tertentu di dalamnya seperti:
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
Tetapi sekali lagi saya tidak berpikir itu sepadan dengan usaha.
$0ada sesuatu selain naskah, yang memang menjawab judul pertanyaan. Namun, saya juga tertarik pada situasi di mana$0skrip itu sendiri, tetapi tidak termasuk direktori. Secara khusus, saya mencoba memahami komentar yang dibuat pada jawaban SO.