En yaygın durumlarda, $0komut dosyasına mutlak veya göreli olarak bir yol içerir, bu nedenle
script_path=$(readlink -e -- "$0")
(bir readlinkkomut olduğu ve desteklediği varsayılarak -e) genellikle kodun kurallı mutlak yolunu elde etmek için yeterince iyi bir yoldur.
$0 yorumlayıcıya iletildiği şekliyle komut dosyasını belirten bağımsız değişkenten atanır.
Örneğin, içinde:
the-shell -shell-options the/script its args
$0alır the/script.
Koştuğunuzda:
the/script its args
Kabuğunuz şunları yapacak:
exec("the/script", ["the/script", "its", "args"])
Komut dosyası, #! /bin/sh -örneğin bir she-bang içeriyorsa , sistem bunu şuna dönüştürecektir:
exec("/bin/sh", ["/bin/sh" or "the/script", "-", "the/script", "its", "args"])
(bir she-bang içermiyorsa veya daha genel olarak sistem bir ENOEXEC hatası döndürürse, aynı şeyi yapacak olan kabuğunuz)
Bazı sistemlerde setuid / setgid komut dosyaları için bir istisna vardır; burada sistem komut dosyasını bazılarında açar fd xve bunun yerine çalışır:
exec("/bin/sh", ["/bin/sh" or "the/script", "-", "/dev/fd/x", "its", "args"])
yarış koşullarından kaçınmak için (bu durumda $0içerecektir /dev/fd/x).
Şimdi, bunu iddia edebilir /dev/fd/x olduğunu o komut dosyası yolu. Ancak, sizden okursanız $0, girdiyi tüketirken komut dosyasını kıracağınızı unutmayın.
Şimdi, çağrıldığı gibi komut dosyası komut adı eğik çizgi içermiyorsa, bir fark var. İçinde:
the-script its args
Sizin kabuk yukarı bakacak the-scriptiçinde $PATH. $PATHbazı dizinlere mutlak veya göreli (boş dize dahil) yollar içerebilir. Örneğin , geçerli dizinde $PATHiçerir /bin:/usr/bin:ve the-scriptbulunursa, kabuk aşağıdakileri yapar:
exec("the-script", ["the-script", "its", "args"])
hangi olacak:
exec("/bin/sh", ["/bin/sh" or "the-script", "-", "the-script", "its", "args"]
Veya şu konumda bulunursa /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 köşe durumu dışında yukarıdaki tüm durumlarda $0, komut dosyasına giden bir yol (mutlak veya göreli) içerecektir.
Şimdi, bir komut dosyası da şu şekilde çağrılabilir:
the-interpreter the-script its args
Tüm the-scriptyukarıda çizgi karakterleri içermeyen, davranış kabuğundan kabuğa biraz değişir.
Eski AT & T kshuygulamaları aslında koşulsuz in-senaryoyu aradılar $PATHbu yüzden, (aslında bir böcek ve setuid komut için bir güvenlik deliği olduğu) $0aslında yoktu değil sürece komut dosyası için bir yolunu içermelidir $PATHarama aslında bulmak oldu the-scriptgeçerli dizinde.
Daha yeni AT&T ksh, the-scriptokunabilirse geçerli dizinde yorumlamaya çalışır . Değilse bir okunabilir için arama ediyorum ve yürütülebilir the-script in $PATH.
İçin basheğer kontrol, the-scriptgeçerli dizinde (ve kırık sembolik bağ değildir) ve değilse, arama (ille çalıştırılabilir) bir okunabilir için the-scriptde $PATH.
zshiçinde shöykünmesi gibi yapacağını basheğer dışında the-scriptgeçerli dizinde bir kırık sembolik bağdır, bir aramak olmaz the-scriptiçinde $PATHve bunun yerine bir hata rapor verecek.
Diğer tüm Bourne benzeri kabuklar görünmüyor the-scriptkadar $PATH.
Zaten tüm bu mermiler için, $0bir içermeyen /ve okunabilir olmayan bulursanız, muhtemelen arandı $PATH. Sonra, içindeki dosyalar $PATHyürütülebilir olması muhtemeldir, muhtemelen command -v -- "$0"yolunu bulmak için kullanmak güvenli bir yaklaşımdır (ancak $0bir kabuk yerleşiminin veya anahtar kelimenin (çoğu kabukta) adı da olsa bu işe yaramaz ).
Yani bu davayı gerçekten kapsamak istiyorsanız, şunu yazabilirsiniz:
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
( ""ekte , ayırıcı yerine ayırıcı olarak işlev gören $PATHkabukları olan boş bir elemanı korumaktır ).$IFS
Şimdi, bir senaryoyu çağırmanın daha ezoterik yolları var. Biri yapabilirdi:
the-shell < the-script
Veya:
cat the-script | the-shell
Bu durumda, yorumlayıcının aldığı $0ilk argüman ( argv[0]) olacaktır , ancak bu genellikle taban adı veya söz konusu tercümana giden bir yol olsa da herhangi bir şey olabilir.the-shell
Bu durumda değerine dayalı olduğunuzu tespit etmek $0güvenilir değildir. ps -o args= -p "$$"Bir ipucu almak için çıktısına bakabilirsiniz . Boru hattında, senaryoya giden bir yola geri dönmenin gerçek bir yolu yoktur.
Bir de yapabilirdi:
the-shell -c '. the-script' blah blih
Daha sonra, içinde hariç zsh(ve Bourne kabuğu bazı eski uygulama), $0olacaktır blah. Yine, bu kabuklardaki senaryonun yoluna ulaşmak zor.
Veya:
the-shell -c "$(cat the-script)" blah blih
vb.
Hakka sahip olduğunuzdan emin olmak için $progname, içinde belirli bir dize arayabilirsiniz:
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
Ama yine de çabaya değeceğini sanmıyorum.
$0, senaryodan başka bir şeyin olduğu ve soru başlığına cevap veren durumları cevapladılar. Ancak,$0betiğin kendisinin olduğu durumlarla da ilgileniyorum , ancak dizini içermiyor. Özellikle, SO cevabı üzerine yapılan yorumu anlamaya çalışıyorum.