İşte asla bilmek istemediğini düşündüğün tek şey:
özet
Bir Bourne benzeri kabuk betiğinde çalıştırılabilir bir dosyanın adını almak için (birkaç uyarı vardır; aşağıya bakınız):
ls=$(command -v ls)
Verilen bir komutun olup olmadığını anlamak için:
if command -v given-command > /dev/null 2>&1; then
echo given-command is available
else
echo given-command is not available
fi
Etkileşimli bir Bourne benzeri kabuğun isteminde:
type ls
whichKomut C-Shell'den kırık mirasıdır ve daha iyi Bourne benzeri kabuklar yalnız bırakılır.
Durumlarda kullanın
Bu bilgiyi bir betiğin parçası olarak veya kabuk isteminde etkileşimli olarak aramak arasında bir fark vardır.
Kabuk isteminde, tipik kullanım durumu şudur: bu komut garip davranır, ben doğru olanı mı kullanıyorum? Yazarken tam olarak ne oldu mycmd? Ne olduğuna daha fazla bakabilir miyim?
Bu durumda, komutu gerçekten çağırmadan komutu çağırdığınızda kabuğunuzun ne yaptığını bilmek istersiniz.
Kabuk betiklerinde oldukça farklı olma eğilimindedir. Bir kabuk betiğinde, tek yapmak istediğin bir komutun nerede veya ne olduğunu bilmek istemenin bir nedeni yok. Genel olarak bilmek istediğiniz, yürütülebilir dosyanın yoludur, bu nedenle ondan daha fazla bilgi edinebilirsiniz (buna göre başka bir dosyaya giden yol gibi veya bu yoldaki yürütülebilir dosyanın içeriğinden bilgi okuyabilirsiniz).
Etkileşimli, hakkında bilmek isteyebilirsiniz tümmy-cmd nadiren bu yüzden komut sistemi üzerinde kullanılabilir komutlar,.
Mevcut araçların çoğu (çoğu zaman olduğu gibi) etkileşimli olarak kullanılmak üzere tasarlanmıştır.
Tarih
İlk önce biraz tarih.
Erken Unix kabukları, 70'lerin sonlarına kadar hiçbir işlevi ya da takma adı bulunmayana kadar koyar. Sadece geleneksel çalışanlar aranıyor $PATH. csh1978 civarında tanıtılan diğer adları (gerçi cshilk edildi yayımlanan içinde 2BSDayrıca işlenmesini Mayıs 1979,) ve .cshrc(gibi her kabuk kabuk özelleştirmek için kullanıcılar cshokur .cshrcbile değilken interaktif komut gibi).
Bourne kabuğu ilk kez 1979'da Unix V7'de piyasaya sürülürken, işlev desteği çok daha sonra eklendi (1984 SVR2'de), ve yine de hiçbir zaman bir rcdosyaya sahip değildi ( .profileortamınızı yapılandırmak, kabuğunu değil ).
csh Bourne kabuğundan çok daha popüler oldu (Bourne kabuğundan çok daha kötü bir sözdizimine sahip olsa da), etkileşimli kullanım için daha kullanışlı ve hoş özellikler ekliyordu.
In 3BSD(1980), bir whichcsh senaryo için eklenmiş cshbir yürütülebilir belirlemenize yardımcı olmak için kullanıcılara ve siz bulabilirsiniz pek farklı bir senaryo which(Solaris, HP / UX, AIX veya Tru64 gibi) günümüzde birçok ticari Unix'lerde.
Bu komut dosyası, kullanıcının okur ~/.cshrc(tüm cshkomut dosyaları gibi çağrılmaz csh -f) ve sağlanan komut adlarını takma adlar listesinde ve içinde $path( cshtemeli koruyan dizi ) arar $PATH.
İşte whichbaşlıyorsunuz, o zamanlar en popüler kabuk için ilk geldi (ve csh90'lı yılların ortasına kadar hala popülerdi), bu kitaplarda belgelenmesinin ana nedenidir ve hala yaygın olarak kullanılmaktadır.
Bir cshkullanıcı için bile , bu whichcsh betiğinin size doğru bilgileri vermesi gerekmediğini unutmayın. Daha ~/.cshrcsonra istemde tanımladığınızlardan değil, örneğin sourcebaşka bir cshdosyayı kullanarak tanımladığınız takma adları alır ve (bu iyi bir fikir olmasa da) PATHyeniden tanımlanabilir ~/.cshrc.
Bu whichkomutu bir Bourne kabuğundan çalıştırmak, hala sizin için tanımlanmış takma adları arar ~/.cshrc, ancak kullanmadığınız için bir tane yoksa csh, muhtemelen size doğru cevabı verir.
Bourne kabuğuna, typeyerleşik komutla SVR2'de 1984'e kadar benzer bir işlevsellik eklenmedi . O (harici bir komut aksine) yerleşik olduğu gerçeği demektir olabilir o kabuğun iç yapıları erişimi nedeniyle size (bir dereceye kadar) doğru bilgiler vermek.
İlk typekomut, whichkomut bulunmazsa , komut dosyasındaki bir başarısızlık çıkış durumu döndürmediği için benzer bir sorundan muzdaripti . Ayrıca, çalıştırılabilirler için, aksine which, komut dosyalarında kullanımı daha az kolaylaştıran bir şey ls is /bin/lsyerine çıktı /bin/ls.
Unix Versiyon 8'in (vahşi doğada serbest bırakılmadığı) Bourne kabuğunun typeismi değiştirildi whatis. Ve plan9 (Unix kez arası olması halefi) kabuk rc(ve bu gibi türevleri akangave es) sahip whatisde.
80'lerin ortasında geliştirilen ancak 1988'den önce yaygın olarak bulunmayan Korn kabuğu (POSIX sh tanımının dayandığı bir alt küme), cshBourne kabuğunun üstüne birçok özellik (satır düzenleyici, takma ad ...) ekledi. . Birkaç seçenek ( kendi benzeri ayrıntılı çıktı sağlamak ve yalnızca çalıştırılabilir dosyaları aramak için (takma adlar / işlevler ...) değil ) alan kendi whenceyapısını (ek olarak type) ekledi .-vtype-p
AT&T ve Berkeley arasındaki telif hakkı sorunlarıyla ilgili kargaşaya tesadüf eseri, 90'ların başında 80'li yılların sonlarında birkaç ücretsiz yazılım kabuğu uygulaması ortaya çıktı. Almquist kabuğunun tamamı (BSD'lerdeki Bourne kabuğunun yerine konması gereken kül), ksh (pdksh) 'in bash(FSF sponsorluğunda ) kamuya açık uygulaması zsh1989 ve 1991 yılları arasında ortaya çıktı.
Ash, Bourne kabuğunun yerine geçmek anlamına gelse de, typedaha sonraya kadar (NetBSD 1.3 ve FreeBSD 2.3'te) bir yerleşime sahip değildi hash -v. OSF / 1 ' /bin/shin typeher zaman 0' a OSF / 1 v3.x 'e geri dönen bir yapısı vardı. bashbir yol eklemedi, whenceancak yolu yazdırmak ( ister gibi ) ve eşleşen tüm komutları bildirmek için bir -pseçenek ekledi . yapılan yerleşik ve katma gibi hareket komutu 's . hepsine sahip.typetype -pwhence -p-atcshwhichwherebashtype -azsh
fishKabuk (2005) bir sahip typebir fonksiyonu olarak uygulanan komutu.
Bu whicharada csh betiği NetBSD'den (tcsh'de yerleşik olduğu ve diğer mermilerde pek kullanılmadığı) kaldırıldı ve (olarak whereisçağrıldığında which, yalnızca çalıştırılabilir dosyalara bakmadığı whereisgibi davranır) eklenen işlevsellik çıkarıldı . OpenBSD’de ve FreeBSD’de, C’de yazılmış komutları yalnızca komutları arayanlar olarak değiştirdik .which$PATHwhich$PATH
Uygulamalar
whichFarklı sözdizimi ve davranışı olan çeşitli Unices üzerinde bir komutun düzinelerce uygulaması vardır .
Linux'ta (içinde yerleşik olanlar yanında tcshve zsh) biz birkaç uygulamalarını bulabilirsiniz. Örneğin en son Debian sistemlerinde, komutları arayan basit bir POSIX kabuk betiğidir $PATH.
busyboxayrıca bir whichkomut var.
Bir Orada GNU whichmuhtemelen en abartılı biri olan. whichCsh betiğinin diğer kabuklara ne yaptığını genişletmeye çalışır : takma adlarınızın ve işlevlerinizin ne olduğunu söyleyebilirsiniz, böylece size daha iyi bir cevap verebilir (ve bazı Linux dağıtımlarının bunun için bazı küresel takma adlar koyduğuna bashinanıyorum) .
zshçalıştırılabilir yoluna genişletmek için birkaç operatöre sahiptir: = dosya adı genişletme operatörü ve :cgeçmiş genişletme değiştiricisi (burada parametre genişletmeye uygulanır ):
$ print -r -- =ls
/bin/ls
$ cmd=ls; print -r -- $cmd:c
/bin/ls
zsh, zsh/parametersmodülde ayrıca komut commandsdizisi ilişkisel dizi olarak tablo yapar :
$ print -r -- $commands[ls]
/bin/ls
Yardımcı whatisprogram (Unix V8 Bourne kabuğundaki veya Plan 9 rc/ ' esdakiler hariç ) gerçekten sadece dokümantasyon için geçerli değildir (whatis veritabanını, man sayfası özeti olan whatis veritabanını tutar).
whereisAyrıca eklendi 3BSDaynı zamanda whicho yazılmış olsa C, değil csh, aynı zamanda, içinde bulundukları ortama göre yürütülebilir, adam sayfası ve kaynak ama hiç de arama için kullanılır. Yani yine, bu farklı bir ihtiyaca cevap veriyor.
Şimdi, standart ön tarafta, POSIX command -vve -Vkomutlarını belirtir (hangi POSIX.2008'e kadar isteğe bağlıydı). UNIX typekomutu belirtir (seçenek yok). Yani hepsi ( where, which, whenceherhangi bir standart belirtilmeyen)
Bazı sürümlere kadar typeve command -vörneğin bazılarının eski sürümlerinin posh( pdkshikisine de sahip olmasına rağmen ) neden olmadığını açıklayan Linux Standard Base spesifikasyonunda isteğe bağlıydı . command -vbazı Bourne kabuğu uygulamalarına (Solaris'teki gibi) de eklendi.
Bugünün Durumu
Bugünlerde durum şu typeve command -vtüm Bourne benzeri mermilerde her yerde bulunmakta (her ne kadar @jarno tarafından belirtildiği gibi bash, POSIX modunda değilken veya yorumlarda aşağıdaki Almquist kabuğunun bazı torunları). tcshkullanmak isteyeceğiniz tek kabuktur which(çünkü orada yoktur typeve whichyerleşiktir).
Dışındaki kabukları içinde tcshve zsh, whichsürece hiçbir ad veya işlev aynı isimle kızımız hiçbirinde olduğu gibi size verilen yürütülebilir yolunu söyleyebilir ~/.cshrc, ~/.bashrcya da herhangi bir kabuk başlatma dosyası ve tanımlamaz $PATHGözlerinde farklı ~/.cshrc. Tanımlanmış bir takma adınız veya işleviniz varsa, bu konuda size söyleyebilecek ya da söylemeyebilir veya yanlış bir şey söyleyebilirsiniz.
Tüm komutları belirli bir adla bilmek istiyorsanız, taşınabilir bir şey yok. Sen kullanmayı tercih wherebölgesi tcshveya zsh, type -aiçinde bashya zsh, whence -aksh93 ve diğer kabuklarda kullanabileceğiniz typebirlikte which -ahangi çalışabilir.
öneriler
Yol adını çalıştırılabilir dosyaya alma
Şimdi, bir betiğin çalıştırılabilir kodunun adını almak için birkaç uyarı var:
ls=$(command -v ls)
Bunu yapmanın standart yolu olurdu.
Ancak birkaç sorun var:
- Çalıştırılabilir dosya yolunu, çalıştırmadan bilmek mümkün değildir. Tüm
type, which, command -v... tüm kullanım sezgiselleri yolunu bulmak için. Onlar aracılığıyla döngü $PATHbileşenleri ve yürütme iznine sahip olan ilk dizin olmayan dosyasını bulun. Bununla birlikte, kabuğa bağlı olarak, komut çalıştırıldığında, birçoğu (Bourne, AT&T ksh, zsh, ash ...) sistem çağrısı bir hata ile dönmeyene $PATHkadar onları sadece yürütecektir. execve. Örneğin, $PATHiçeriyorsa /foo:/barve yürütmek istiyorsanız ls, önce yürütmeye çalışacaklar /foo/lsveya başarısız olursa /bar/ls. Şimdi yürütme/foo/lsYürütme izniniz olmadığından ancak geçerli bir çalıştırılabilir olmadığından başka nedenlerden dolayı başarısız olabilir. için yürütme izniniz varsa command -v lsrapor /foo/lseder /foo/ls, ancak geçerli bir lsçalıştırılabilir /bar/lsdeğilse /foo/ls, çalıştırma işlemi gerçekten çalışabilir .
- Eğer
foobir yerleşik ya da fonksiyon ya da diğer adı olan, command -v foodöner foo. Boş dizgiyi içeriyorsa ve geçerli dizinde çalıştırılabilir bir dosya varsa ash, pdkshveya gibi bazı kabuklarda zshda döndürülebilir . Bunu dikkate almanız gerekebilecek bazı durumlar vardır. Örneğin, yerleşiklerin listesinin kabuk uygulamasına bağlı olduğunu unutmayın (örneğin, bazen meşgul kutusu için yerleşiktir ) ve örneğin ortamdan işlevler alabilir.foo$PATHfoomountshbash
- Eğer
$PATH(tipik olarak göreceli yol bileşenleri içeren .ya da her ikisi geçerli dizine bakınız başka bir şey olabilir boş dize), kabuk bağlı command -v cmdolabilir çıkış mutlak bir yolu. Bu nedenle koşarken elde ettiğiniz yol, başka bir yerden command -vsonra geçerli cdolmayacaktır.
- Anekdot: eğer ksh93 kabuk ile,
/opt/ast/bin(yani tam yol inanıyorum farklı sistemlerde farklı olabilir gerçi) senin içinde $PATH, ksh93 mevcut birkaç ekstra yerleşiklerinden (yapacaktır chmod, cmp, cat...), ama command -v chmoddönecektir /opt/ast/bin/chmodo yolun kokan bile t var.
Bir komutun olup olmadığını belirleme
Belirli bir komutun standart olarak olup olmadığını öğrenmek için şunları yapabilirsiniz:
if command -v given-command > /dev/null 2>&1; then
echo given-command is available
else
echo given-command is not available
fi
Nerede kullanmak istersin? which
(t)csh
İçinde cshve tcshfazla seçeneğiniz yok. İçinde tcsholduğu gibi iyidir which. Bu csh, whichbirkaç durumda istediğiniz şeyi yapamayabileceğiniz sistem komutu olacaktır .
komutları sadece bazı mermilerde bul
Kullanmanın mantıklı olabileceği bir durum which, bir komutun yolunu bilmek, potansiyel kabuk yapılarını veya işlevlerini bash, csh(değil tcsh) dashya da Bournekabuk komut dosyalarında yok sayarak whence -p(gibi kshya da zsh) kabuk komut dosyalarını görmezden gelmek isteyip istemediğinizdir. , command -ev(like yash), whatis -p( rc, akanga) veya mevcut olan ve script olmayan sistemlerdeki bir yerleşik which(like tcshveya zsh) .whichcsh
Bu koşullar yerine getirilirse, o zaman:
echo=$(which echo)
Size ilk yolunu verecekti echoiçinde $PATH(köşe durumlar haricinde) ne olursa olsun, olsun echoda bir kabuk yerleşik / takma / fonksiyon ya da olmamak olur.
Diğer kabuklarda, tercih edersiniz:
- zsh :
echo==echoveya echo=$commands[echo]veyaecho=${${:-echo}:c}
- ksh , zsh :
echo=$(whence -p echo)
- yaş :
echo=$(command -ev echo)
- rc , akanga :
echo=`whatis -p echo`(boşluklu yollara dikkat et)
- balık :
set echo (type -fp echo)
Yapmanız gereken tek şey bu komutu çalıştırmak ise echo, onun yolunu almak zorunda değilsiniz, sadece şunu yapabilirsiniz:
env echo this is not echoed by the builtin echo
Örneğin tcsh, yerleşimin whichkullanılmasını önlemek için :
set Echo = "`env which echo`"
harici bir komuta ihtiyaç duyduğunuzda
Kullanmak isteyebileceğiniz başka bir durum which, aslında harici bir komuta ihtiyaç duyduğunuzda olabilir . POSIX, tüm kabuk yerleşiklerinin (gibi command) harici komutlar olarak da kullanılabilmesini gerektirir , ancak ne yazık ki commandpek çok sistem için geçerli değildir . Örneğin command, Linux tabanlı işletim sistemlerinde bir komut bulmak nadirdir which( birçoğunda bir komut olsa da (farklı seçenekler ve davranışlar içeren farklı olsalar)).
Harici bir komut isteyebileceğiniz durumlar, bir POSIX kabuğunu çağırmadan bir komutu yerine getireceğiniz her yerde olur.
system("some command line"), popen()... C veya çeşitli dillerde yerine getirdiği işlevleri komut satırı ayrıştırmak için bir kabuk çağırmak, böylece do system("command -v my-cmd")onları çalışma yapmak. Bunun bir istisnası, perlherhangi bir özel kabuk karakteri (boşluk dışında) görmezse, kabuğu en iyi duruma getirmesi olabilir . Bu aynı zamanda backtick operatörü için de geçerlidir:
$ perl -le 'print system "command -v emacs"'
-1
$ perl -le 'print system ":;command -v emacs"'
/usr/bin/emacs
0
$ perl -e 'print `command -v emacs`'
$ perl -e 'print `:;command -v emacs`'
/usr/bin/emacs
Yukarıdakilerin eklenmesi, orada bir kabuk çağırmaya :;zorlar perl. Kullanarak which, bu numarayı kullanmak zorunda kalmazsınız.
whichetkileşimli bir kabuk bağlamı varsayıyor. Bu soru etiketlendi / taşınabilirlik. Bu yüzden, soruyu bu bağlamda "whichverilen adın ilk çalıştırılabilirini bulmak yerine ne kullanmalıyım" olarak yorumluyorum$PATH. Çoğuwhichgerçek dünyada taşınabilir kabuk komut dosyalarında sadece akademik ilgi alanı bulunan takma adlar, yerleşikler ve işlevlerle başa çıkmanın en çok yanıtı ve nedeni . Yerel olarak tanımlanmış diğer adlar, bir kabuk betiği çalıştırılırken miras alınmaz (kaynak göstermediğiniz sürece.).