Kun etsit polkua suoritettavaan tiedostoon tai tarkistat mitä tapahtuisi, jos annat komennon nimen Unix-kuoreen, siellä on lukuisia erilaisia apuohjelmia ( which
, type
, command
, whence
, where
, whereis
, whatis
, hash
jne.).
Kuulemme usein, että which
tulisi välttää. Miksi? Mitä meidän pitäisi käyttää sen sijaan?
Kommentit
Vastaa
Tässä on kaikki mitä et koskaan ajatellut, ettet koskaan halua tietää siitä:
Yhteenveto
Saat Bourne-tyyppisessä shell-komentosarjassa suoritettavan suoritettavan tiedoston polku (muutamia varoituksia; katso alla):
ls=$(command -v ls)
Voit selvittää, onko annettu komento:
if command -v given-command > /dev/null 2>&1; then echo given-command is available else echo given-command is not available fi
Interaktiivisen Bourne-tyyppisen kuoren kehotteessa:
type ls
which
-komento on rikki C-Shellin perintö, ja se on parempi jättää yksin Bournen kaltaisiin kuoreisiin.
Käytä tapauksia
Siellä ”Ero näiden tietojen etsimisen osana komentosarjaa tai vuorovaikutteisesti komentokehotteessa.
Kuorikehotteessa tyypillinen käyttötapaus on: tämä komento käyttäytyy oudosti, käytänkö oikea? Mitä tapahtui, kun kirjoitin mycmd
? Voinko tarkastella tarkemmin, mitä se on?
Siinä tapauksessa haluat tietää, mitä komentotulkki tekee, kun käynnistät komennon käynnistämättä komentoa.
Kuoriskripteissä se on yleensä melko erilainen. Shell-komentosarjassa ei ole mitään syytä, miksi haluat tietää, missä tai mikä komento on, jos haluat vain suorittaa sen. Yleensä mitä haluat tietää, on suoritettavan tiedoston polku, joten voit saada siitä enemmän tietoja (kuten toisen tiedoston polku verrattuna siihen tai lukea tietoja kyseisen polun suoritettavan tiedoston sisällöstä).
Vuorovaikutteisesti saatat haluta tietää kaikista järjestelmässä käytettävissä olevista my-cmd
-komennoista skripteinä, harvoin niin.
Suurin osa käytettävissä olevista työkaluista (kuten usein tapahtuu) on suunniteltu käytettäväksi vuorovaikutteisesti.
Historia
Ensin vähän historiaa.
Varhaisissa Unix-kuorissa 70-luvun loppupuolelle saakka ei ollut toimintoja tai aliaksia. Vain perinteinen suoritettavien tiedostojen haku hakemistossa $PATH
. csh
esitteli aliaksia noin 1978 (vaikka csh
julkaistiin ensin julkaistuna kohdassa 2BSD
, toukokuussa 1979), ja myös .cshrc
-prosessin käsittely käyttäjille kuoren mukauttamiseksi (jokainen kuori, kuten csh
, lukee .cshrc
silloinkin, kun se ei ole vuorovaikutteinen kuten komentosarjoissa).
Vaikka Bourne-kuori julkaistiin ensimmäisen kerran Unix V7: ssä aiemmin vuonna 1979, toimintojen tuki lisättiin vain paljon myöhemmin (1984 SVR2: ssa), ja joka tapauksessa sillä ei koskaan ollut rc
-tiedostoa (.profile
on määritettävä ympäristö, ei kuori per se ).
csh
sai paljon suositumpaa kuin Bourne-kuori, koska (vaikka sen syntaksit olivat hirvittävän huonommat kuin Bourne-kuori), se lisäsi paljon mukavampia ja mukavampia ominaisuuksia vuorovaikutteiseen käyttöön.
3BSD
(1980) -lehdessä which
csh -komentosarja lisättiin csh
-käyttäjille helpottamaan suoritettavaa tiedostoa, ja se on tuskin erilainen skripti, jonka löydät nimellä which
nykyään monissa kaupallisissa laitteissa (kuten Solaris, HP / UX, AIX tai Tru64).
Tämä komentosarja lukee käyttäjän” s ~/.cshrc
(kuten kaikki csh
-skriptit tekevät, ellei niitä kutsuta csh -f
-toiminnolla), ja etsii annetut komentojen nimet aliaksiluettelosta ja ryhmässä $path
(taulukko, jota csh
ylläpitää $PATH
perusteella).
Täällä: which
oli tuolloin suosituimman kuoren ensimmäinen (ja csh
oli edelleen suosittu 90-luvulla), mikä on tärkein syy siihen, miksi se dokumentoitiin kirjoissa ja jota käytetään edelleen laajalti.
Huomaa, että csh
-käyttäjälle, id = ”9b39b47e6e”>
csh-komentosarja ei välttämättä anna sinulle oikeat tiedot. Se saa aliakset, jotka on määritelty kohdassa~/.cshrc
, ei niitä, jotka olet määrittänyt myöhemmin kehotteessa tai esimerkiksisource
muodostamalla toisencsh
-tiedosto, ja (vaikka se ei olekaan hyvä idea),PATH
voidaan määritellä uudelleen osastossa~/.cshrc
.
Tämän which
-komennon suorittaminen Bourne-kuoresta haisi silti ~/.cshrc
-palvelussa määritettyjä aliaksia, mutta jos sinulla ei ole sellaista, koska et käytä csh
, se todennäköisesti saisi oikean vastauksen.
Vastaavaa toimintoa ei lisätty Bourne-kuori vuoteen 1984 SVR2: ssa sisäänrakennetulla type
-komennolla. Se, että se on sisäänrakennettu (toisin kuin ulkoinen komentosarja), tarkoittaa, että se voi antaa sinulle oikeat tiedot (jossain määrin), koska sillä on pääsy kuoren sisäosiin.
Alkuperäinen komento type
kärsi samanlaisesta ongelmasta kuin komentosarja which
, koska se ei palauttanut vikatilanteen tilaa, jos komentoa ei löytynyt. Toisin kuin which
, suoritettaville tiedostoille se antaa jotain ls is /bin/ls
-tyyppistä pelkän mikä helpotti sen käyttöä komentosarjoissa.
Unix-version 8″ (ei julkaistu luonnossa) Bourne-kuoressa oli ”s type
sisäänrakennettu uudelleen nimeksi whatis
. Ja Plan9 (Unixin kerran tuleva seuraaja) kuori rc
(ja sen johdannaisilla kuten akanga
ja es
) on myös whatis
.
Korn-kuori (jonka osajoukko 80-luvun puolivälissä kehitetty POSIX sh
-määritys perustuu), joka ei ollut laajalti saatavilla ennen vuotta 1988, ja lisäsi monia csh
-ominaisuuksia ( rivieditori, aliakset …) Bourne-kuoren päällä. Se lisäsi oman whence
sisäänrakennetun (lisäksi type
), joka otti useita vaihtoehtoja (-v
toimittaa type
-tyyppisen sanatulostuksen ja -p
etsimään vain suoritettavia tiedostoja (ei aliaksia / toimintoja …)) .
Samanaikaisesti AT & T: n ja Berkeleyn välisten tekijänoikeuskysymysten kanssa vallitsevaan myllerrykseen tuli muutama ilmainen ohjelmisto -kuoren toteutus. 80-luvun lopulla 90-luvun alussa.Kaikki Almquist-kuori (ash
, joka korvaa Bourne-kuoren BSD-tiedostoissa), ksh
(pdksh
), bash
(FSF: n sponsoroima), zsh
ilmestyi vuoden 1989 ja 1991.
Vaikka Ash oli tarkoitettu korvaamaan Bourne-kuori, sillä ei ollut type
-rakennetta vasta paljon myöhemmin (NetBSD 1.3: ssa ja FreeBSD 2.3: ssa). ), vaikka sillä oli hash -v
. OSF / 1 /bin/sh
: ssä oli sisäänrakennettu type
joka palautti 0 OSF / 1 v3.x: ään. bash
ei lisännyt whence
, mutta lisäsi -p
vaihtoehto type
polun tulostamiseksi (type -p
olisi kuin whence -p
) ja -a
raportoidaksesi kaikki vastaavat komennot. tcsh
teki which
sisäisen ja lisäsi where
-komennon, joka toimii kuten bash
” s type -a
. zsh
on ne kaikki.
fish
shell (2005) -komennolla type
on toiminto.
which
csh-skripti poistettiin sillä välin NetBSD: ltä (koska se oli sisäänrakennettu tcsh: ssä eikä siitä ole paljon hyötyä muissa kuoreissa), ja toiminto lisättiin osioon whereis
(kutsutaan nimellä which
, whereis
käyttäytyy kuten which
, paitsi että se etsii vain suoritettavia tiedostoja ryhmästä iv id = ”00879d7bee” OpenBSD: ssä ja FreeBSD: ssä myös which
muutettiin C-kirjaimeksi, joka etsii komentoja vain $PATH
.
Toteutukset
which
co: n toteutuksia on kymmeniä mmand useilla Unice-laitteilla, joilla on erilainen syntaksi ja käyttäytyminen.
Linuxissa (sisäänrakennettujen lisäksi tcsh
ja zsh
) löydämme useita toteutuksia. Esimerkiksi viimeaikaisissa Debian-järjestelmissä se on yksinkertainen POSIX-komentotulkkikomento, joka etsii komentoja $PATH
.
busybox
: lla on myös which
-komento.
On olemassa GNU
which
, joka on luultavasti kaikkein ylellisin. Se yrittää laajentaa which
csh -skriptin tekoa muille kuoreille: voit kertoa sille, mitkä ovat aliaksesi ja toimintosi, jotta se voi antaa sinulle parempi vastaus (ja uskon, että jotkut Linux-jakelut asettavat sen ympärille joitain globaaleja aliaksia bash
varten).
zsh
: llä on pari operaattoria laajennettavaksi suoritettavien tiedostojen polulle: =
tiedostonimen laajennus ja :c
historialaajennuksen muokkaus (käytetään tässä parametrilaajennukseen ):
$ print -r -- =ls /bin/ls $ cmd=ls; print -r -- $cmd:c /bin/ls
zsh
, -moduuli tekee myös komennon hajautustaulukon commands
-yhdistelmäryhmänä:
$ print -r -- $commands[ls] /bin/ls
whatis
-apuohjelma (paitsi Unix V8 Bourne -kuoressa tai Suunnitelma 9 rc
/ es
) ei todellakaan ole yhteydessä toisiinsa, koska se on tarkoitettu vain dokumentaatioon (tarttuu whatis-tietokantaan, ts. man-sivun yhteenvetoon).
whereis
oli myös lisätty tiedostoon 3BSD
samaan aikaan kuin which
, vaikka se kirjoitettiin C
, ei csh
ja sitä käytetään etsimään samanaikaisesti suoritettavaa tiedostoa, man-sivua ja lähdettä, mutta se ei perustu nykyiseen ympäristöön. Joten jälleen, tämä vastaa toiseen tarpeeseen.
Nyt POSIX määrittää vakiopuolella command -v
ja -V
-komennot (jotka olivat aiemmin valinnaisia POSIX.2008 asti). UNIX määrittää type
-komennon (ei vaihtoehtoa). Että kaikkia (where
, which
, whence
ei määritetä missään standardissa) .
Joitakin versioita saakka type
ja command -v
olivat valinnaisia Linux Standard Base -määrityksessä, mikä selittää miksi esimerkiksi joillakin posh
-versioilla (vaikka ne perustuivatkin pdksh
-ohjelmaan, joissa molemmat olivat) ei ollut kumpaakaan. command -v
lisättiin myös joihinkin Bourne-shell-toteutuksiin (kuten Solarisissa).
Tila tänään
Nykyään tila on, että type
ja command -v
ovat läsnä kaikkialla Bournen kaltaiset kuoret (huomaa kuitenkin, kuten @jarno huomautti, huomautus / virhe kohdasta bash
, kun et ole POSIX-tilassa, tai joitain Almquist-kuoren jälkeläisiä alla olevissa kommenteissa) tcsh
on ainoa kuori, jossa haluat käyttää which
(koska ei ole type
siellä ja which
on sisäänrakennettu).
Muissa kuoreissa kuin tcsh
ja zsh
, which
saattaa kertoa sinulle annetun suoritettavan tiedoston polun, kunhan missään ~/.cshrc
, ~/.bashrc
tai mitä tahansa komentotulkin käynnistystiedostoa, etkä määritä $PATH
~/.cshrc
. Jos sinulla on määritetty alias tai toiminto, se saattaa kertoa sinulle tai olla kertomatta sinulle tai kertoa väärän asian.
Jos haluat tietää Kaikista tietyn nimen komennoista ei ole mitään kannettavaa. Käytä where
ryhmässä tcsh
tai zsh
, type -a
bash
tai zsh
, whence -a
muodossa ksh93 ja muissa kuoreissa , voit käyttää type
yhdessä which -a
: n kanssa, mikä saattaa toimia.
Suositukset
Polunimen saaminen suoritettavaan tiedostoon
Saadaksesi suoritettavan tiedoston polun komentosarjaan, on olemassa muutamia varoituksia:
ls=$(command -v ls)
olisi tavanomainen tapa tehdä se.
On kuitenkin muutama ongelma:
- Suoritettavan tiedoston polkua ei voida tietää suorittamatta sitä.
type
,which
,command -v
… kaikki käyttävät heuristiikkaa polun selvittämiseen He etenevät$PATH
-komponenttien läpi ja löytävät ensimmäisen hakemistotiedoston, jolle sinulla on käyttöoikeus. Kun komento suoritetaan kuoressa, monet heistä (Bourne, AT & T ksh, zsh, ash …) vain suorittavat ne järjestyksessä$PATH
kunnesexecve
-järjestelmäkutsu ei palaa virheellä. Esimerkiksi jos$PATH
sisältää/foo:/bar
ja haluat suorittaals
, he yrittävät ensin suorittaa/foo/ls
tai jos se epäonnistuu/bar/ls
./foo/ls
-sovelluksen suoritus voi nyt epäonnistua, koska sinulla ei ole suorituslupaa, mutta myös monista muista syistä, kuten se ei ole kelvollinen suoritettava tiedosto.command -v ls
raportoi/foo/ls
, jos sinulla on suorituslupa kohteelle/foo/ls
, mutta käynnissäls
saattaa todella suorittaa/bar/ls
, jos/foo/ls
ei ole kelvollinen suoritettava tiedosto. - jos
foo
on sisäänrakennettu tai funktio tai alias,command -v foo
palauttaafoo
. Joillakin kuorilla, kutenash
,pdksh
taizsh
, se voi myös palauttaafoo
jos$PATH
sisältää tyhjän merkkijonon ja nykyisessä hakemistossa on suoritettavafoo
-tiedosto. Joissakin olosuhteissa sinun on ehkä otettava tämä huomioon. Pidä mielessä, että sisäänrakennettujen luettelo vaihtelee kuoren toteutuksen mukaan (esimerkiksimount
on joskus sisäänrakennettu busyboxillesh
), ja esimerkiksibash
voi saada toimintoja ympäristöstä. - jos
$PATH
sisältää suhteelliset polkukomponentit (tyypillisesti.
tai tyhjä merkkijono, jotka molemmat viittaavat nykyiseen hakemistoon, mutta voivat olla mitä tahansa) kuoresta riippuen,command -v cmd
ei välttämättä tuota absoluuttista polkua. Joten polku, jonka hankit ajaessasi ei ole enää voimassa, kun oletcd
jossakin muualla. - Anekdootti: ksh93-kuoren kanssa, jos
/opt/ast/bin
(tosin tarkka polku voi vaihdella eri järjestelmissä, joiden uskon olevan) on sinussa$PATH
, ksh93 asettaa saataville muutaman ylimääräisen sisäänrakennetun version (chmod
,cmp
,cat
…), muttacommand -v chmod
palauttaa/opt/ast/bin/chmod
, vaikka polkua ei olisikaan.
Komennon olemassaolon selvittäminen
Voit selvittää tietyn komennon olemassaolon seuraavasti:
if command -v given-command > /dev/null 2>&1; then echo given-command is available else echo given-command is not available fi
Missä voidaan käyttää which
(t)csh
Kohteissa csh
ja tcsh
sinulla ei ole paljon valinnanvaraa. Kohdassa tcsh
”hieno, kun which
on sisäänrakennettu. Kohdassa csh
se on järjestelmä which
-komento, joka ei välttämättä tee haluamaasi joissakin tapauksissa.
Etsi komentoja vain joistakin simpukoista
Tapaus, jossa which
on järkevää käyttää, on, jos haluat tietää komennon polun jättämättä potentiaalia sisäiset shell-toiminnot tai toiminnot bash
, csh
(ei tcsh
), dash
tai Bourne
shell-komentosarjat, eli kuoret, joilla ei ole whence -p
(kuten ksh
tai zsh
), command -ev
(kuten yash
), whatis -p
(rc
, akanga
) tai sisäänrakennettu which
(kuten tcsh
tai zsh
) järjestelmissä, joissa which
on käytettävissä, eikä se ole csh
-skripti.
Jos nämä ehdot täyttyvät, niin:
echo=$(which echo)
saat ensimmäisen echo
ryhmässä $PATH
(paitsi kulmatapauksissa) riippumatta siitä, onko echo
myös kuori sisäänrakennettu / alias / function tai ei.
Muissa kuorissa haluat:
- zsh :
echo==echo
taiecho=$commands[echo]
taiecho=${${:-echo}:c}
- ksh , zsh :
echo=$(whence -p echo)
- yash :
echo=$(command -ev echo)
- rc , akanga :
echo=`whatis -p echo`
(varo välilyöntejä sisältäviä polkuja) - kala :
set echo (type -fp echo)
Huomaa, että jos haluat vain suorittaa että echo
-komento, sinun ei tarvitse saada sen polkua, voit tehdä vain:
env echo this is not echoed by the builtin echo
Esimerkiksi: tcsh
, estämään sisäänrakennetun which
: n käyttöä:
set Echo = "`env which echo`"
Kun tarvitset ulkoista komentoa
Toinen tapaus, jossa haluat ehkä käyttää which
, on, kun todella tarvitset tarvetta ulkoinen komento. POSIX edellyttää, että kaikki kuoren sisäänrakennetut sisäosat (kuten command
) ovat saatavilla myös ulkoisina komentoina, mutta valitettavasti näin ei ole command
monissa järjestelmissä. Esimerkiksi command
-komento löytyy harvoin Linux-pohjaisista käyttöjärjestelmistä, kun taas useimmilla niistä on which
-komento (tosin erilaisia, joilla on eri vaihtoehdot ja käyttäytymismallit).
Tapaukset, joissa haluat ehkä ulkoisen komennon, ovat missä tahansa, missä suoritat komennon kutsumatta POSIX-komentotulkkia.
system("some command line")
, popen()
… C: n tai useiden eri kielten toiminnot kutsuvat kuoren jäsentämään komentoriviä, joten system("command -v my-cmd")
tehdä työtä niissä. Poikkeus tästä olisi perl
, joka optimoi kuoren, jos se ei näe mitään shell-erikoismerkkiä (muuta kuin välilyönti). Tämä pätee myös sen backtick-operaattoriin:
$ 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
Yllä olevan :;
lisääminen pakottaa perl
kutsumaan kuoren Käyttämällä which
, sinun ei tarvitse käyttää tätä temppua.
Kommentit
- @Joe,
which
oncsh
-skripti monissa kaupallisissa yksiköissä. Syy on historiallinen, että ’ miksi annoin historian, jotta ihmiset ymmärtäisivät, mistä se tuli, miksi ihmiset tottuivat siihen ja miksi itse asiassa siellä ’ ei ole mitään syytä sinun pitäisi käyttää sitä. Ja kyllä, jotkut ihmiset käyttävät (t) csh: tä. Kaikki eivät vielä käytä Linuxia. - Tämän viestin lukemisen jälkeen olen löytänyt paljon kontekstia vastaukselle, mutta en itse vastausta.Missä tässä viestissä todellakin sanotaan, miksi ei käytä
which
, toisin kuin asiat, joita yrität käyttääwhich
tehtävä,which
-historia,which
-toteutukset, muut komennot liittyvien tehtävien suorittamiseen tai syyt tosiasialliseen käyttöönwhich
? Miksi muut komennot ovat parempia ? Mitä he tekevät eri tavalla kuinwhich
? Kuinka he välttävät sen sudenkuopat? Tämä vastaus kuluttaa todellisuudessa enemmän sanoja vaihtoehtojen ongelmiin kuinwhich
-ongelmiin. -
command
on kuvattu kirjoittanut POSIX. - @St é phaneChazelas Jos luot uuden tiedoston
touch /usr/bin/mytestfile
ja suoritan sen jälkeencommand -v mytestfile
, se antaa polun (kun taaswhich mytestfile
ei). - @jarno, kyllä, sinä ’ on oikeassa.
bash
asettuu tiedostoon, jota ei voida suorittaa, jos se ’ ei löydä suoritettavaa tiedostoa, joten se ’ s ” OK ” (tosin käytännössä mieluummincommand -v
/type
palauttaa virheen), koska se ’ on komento, jonka se yrittää suorittaa, kun suoritatmytestfile
, muttadash
-käyttäytyminen on buginen, ikään kuin ’ sa ei voi suorittaacmd
ennen suoritettavaa,command -v
palauttaa suorittamattoman, kuncmd
suoritetaan suoritettava (väärä yksi on myös hajautettu). FreeBSD: lläsh
(perustuu myösash
) on sama vika. zsh, yash, ksh, mksh, bash kuten sh ovat kunnossa.
Vastaa
Syyt miksi ei halua käyttää which
on jo selitetty, mutta tässä on muutama esimerkki muutamasta järjestelmästä, jossa which
todella epäonnistuu.
Bournen kaltaisissa kuorissa verrataan uudelleen which
-lähtöä type
(type
koska se on sisäänrakennettu kuori, sen on tarkoitus olla perustotuus, koska se on kuori, joka kertoo meille, kuinka se käynnistää komennon).
Monet tapaukset ovat corner -tapauksia, mutta pidä mielessä, että which
/ type
käytetään usein kulmatapauksissa (vastauksen löytämiseksi) odottamattomaan käyttäytymiseen, kuten: miksi komento käyttäytyy tuolla tavalla, kumpaakin kutsun? ).
Useimmat järjestelmät, useimmat Bourne-tyyppiset kuoret: toiminnot
Ilmeisin tapaus koskee funktioita:
$ type ls ls is a function ls () { [ -t 1 ] && set -- -F "$@"; command ls "$@" } $ which ls /bin/ls
Syynä on se, että which
raportoi vain suoritettavista tiedostoista ja joskus aliaksista (vaikkakaan ei aina sinun kuoresi), ei funktioista.
GNU: n man -sivulla on rikki (koska unohdettiin lainata $@
) esimerkki siitä, kuinka sitä voidaan käyttää myös toimintojen raportointiin, mutta kuten aliaksia, koska se ei toteuta kuoren syntaksin jäsentäjää, se hämmentyy helposti:
$ which() { (alias; declare -f) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot "$@";} $ f() { echo $"\n}\ng ()\n{ echo bar;\n}\n" >> ~/foo; } $ type f f is a function f () { echo " } g () { echo bar; } " >> ~/foo } $ type g bash: type: g: not found $ which f f () { echo " } $ which g g () { echo bar; }
Useimmat järjestelmät, useimmat Bourne-tyyppiset kuoret: sisäänrakennetut
Toinen ilmeinen tapaus on sisäänrakennettuja tai avainsanoja, koska which
ulkoisena komennona ei ole mitään keinoa tietää, mitkä sisäiset komentot shellilläsi ovat (ja jotkut kuoret, kuten zsh
, bash
tai ksh
voi ladata sisäänrakennettuja tiedostoja dynaamisesti):
$ type echo . time echo is a shell builtin . is a shell builtin time is a shell keyword $ which echo . time /bin/echo which: no . in (/bin:/usr/bin) /usr/bin/time
(tämä ei koske zsh
, johon which
on rakennettu)
Solaris 10, AIX 7.1, HP / UX 11i, Tru64 5. 1 ja monet muut:
$ csh % which ls ls: aliased to ls -F % unalias ls % which ls ls: aliased to ls -F % ksh $ which ls ls: aliased to ls -F $ type ls ls is a tracked alias for /usr/bin/ls
Tämä johtuu siitä, että useimmissa kaupallisissa yksiköissä which
(kuten alkuperäisessä toteutuksessa) 3BSD: llä) on csh
komentosarja, joka lukee ~/.cshrc
. Alias, jonka se raportoi, on määritelty siellä riippumatta tällä hetkellä määrittämistäsi aliaksista ja siitä, mitä kuorta todella käytät.
HP / UX tai Tru64:
% echo "setenv PATH /bin:/usr/bin" >> ~/.cshrc % setenv PATH ~/bin:/bin:/usr/bin % ln -s /bin/ls ~/bin/ % which ls /bin/ls
(Solaris- ja AIX-versiot ovat korjanneet ongelman tallentamalla $path
ennen kuin luit ~/.cshrc
ja palauttaa se ennen komentojen hakemista)
$ type "a b" a b is /home/stephane/bin/a b $ which "a b" no a in /usr/sbin /usr/bin no b in /usr/sbin /usr/bin
Tai:
$ d="$HOME/my bin" $ mkdir "$d"; PATH=$PATH:$d $ ln -s /bin/ls "$d/myls" $ type myls myls is /home/stephane/my bin/myls $ which myls no myls in /usr/sbin /usr/bin /home/stephane/my bin
(tietysti csh
-komentosarjana et voi odottaa sen toimivan välilyöntejä sisältävillä argumenteilla …)
CentOS 6.4, bash
$ type which which is aliased to `alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde" $ alias foo=": "|test|"" $ which foo alias foo=": "|test|"" /usr/bin/test $ alias $"foo=\nalias bar=" $ unalias bar -bash: unalias: bar: not found $ which bar alias bar="
Kyseisessä järjestelmässä on koko järjestelmän määrittämä alias, joka kietoo GNU which
-komennon.
Väärä tuotos johtuu siitä, että which
lukee bash
”s alias
mutta ei osaa jäsentää sitä oikein ja käyttää heuristiikkaa (yksi alias riviä kohti, etsii ensimmäisen löydetyn komennon |
, , &
…)
CentOSin pahin asia on se, että zsh
on täysin hieno which
sisäänrakennettu komento, mutta CentOS onnistui hajottamaan sen korvaamalla sen toimimattomalla aliaksella GNU which
.
Debian 7.0, ksh93:
(tosin koskee useimpia järjestelmiä, joissa on useita kuoria)
$ unset PATH $ which which /usr/local/bin/which $ type which which is a tracked alias for /bin/which
Debianissa /bin/which
on komentosarja /bin/sh
. Minun tapauksessani sh
on dash
, mutta se on sama, kun se ”s bash
.
Poistamaton PATH
ei ole poistaa käytöstä PATH
-haku, vaan tarkoittaa järjestelmän käyttämistä ”s oletuspolku , josta valitettavasti Debianissa kukaan ei ole samaa mieltä (dash
ja bash
on /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
, zsh
on /bin:/usr/bin:/usr/ucb:/usr/local/bin
, ksh93
on /bin:/usr/bin
, mksh
on /usr/bin:/bin
($(getconf PATH)
), execvp()
(kuten kohdassa env
) on :/bin:/usr/bin
(kyllä, näyttää ensin nykyisen hakemiston!)) .
Siksi which
menee väärin yllä, koska se käyttää dash
”oletus PATH
joka poikkeaa ksh93
”s
Se” ei ” parempi kuin GNU which
, joka raportoi:
which: no which in ((null))
(mielenkiintoista on, että /usr/local/bin/which
järjestelmässäni, joka on itse asiassa akanga
-skripti, jonka mukana tuli akanga
(rc
kuorijohdannainen, jossa oletuksena PATH
on /usr/ucb:/usr/bin:/bin:.
)))
bash, mikä tahansa järjestelmä:
Yksi Chris viittaa vastauksessaan :
$ PATH=$HOME/bin:/bin $ ls /dev/null /dev/null $ cp /bin/ls bin $ type ls ls is hashed (/bin/ls) $ command -v ls /bin/ls $ which ls /home/chazelas/bin/ls
Myös soittamisen jälkeen hash
manuaalisesti:
$ type -a which which is /usr/local/bin/which which is /usr/bin/which which is /bin/which $ hash -p /bin/which which $ which which /usr/local/bin/which $ type which which is hashed (/bin/which)
Nyt tapaus, jossa which
ja joskus type
epäonnistuu:
$ mkdir a b $ echo "#!/bin/echo" > a/foo $ echo "#!/" > b/foo $ chmod +x a/foo b/foo $ PATH=b:a:$PATH $ which foo b/foo $ type foo foo is b/foo
Nyt joillakin kuorilla:
$ foo bash: ./b/foo: /: bad interpreter: Permission denied
Muiden kanssa:
$ foo a/foo
Ei which
eikä type
voi tietää etukäteen, että b/foo
ei voi b Suoritettu. Jotkut kuoret, kuten bash
, ksh
tai yash
, kun kutsutaan foo
yrittää todellakin suorittaa b/foo
ja ilmoittaa virheestä, kun taas toiset (kuten zsh
, ash
, csh
, Bourne
, tcsh
) suoritetaan a/foo
execve()
-järjestelmän kutsun epäonnistumisen yhteydessä b/foo
.
Kommentit
-
mksh
käyttää oletusarvoisesti jotakin erilaista$PATH
: ensin , käyttöjärjestelmän käännösaikavakiota_PATH_DEFPATH
käytetään (yleisimmin BSD-levyillä), sitten käytetäänconfstr(_CS_PATH, …)
(POSIX), ja jos molempia ei ole tai ne epäonnistuvat, käytetään/bin:/usr/bin:/sbin:/usr/sbin
. - Ensimmäisessä esimerkissä, vaikka
ls
on funktio, jota käytetään gls
polusta PATH. Jawhich
on hyvä kertoa, mitä niistä käytetään/usr/bin/ls
tai/usr/local/bin/ls
. En näe ’ en näe ” Miksi en käyttäisi sitä, mikä ” …. - @rudimeier, Se
which ls
antaa minulle/bin/ls
riippumatta siitä, onkols
-funktiokutsut/bin/ls
tai/opt/gnu/bin/ls
taidir
tai ei mitään. IOW,which
(mitä toteutukset, IMMV) antaa jotain merkityksetöntä - @St é phaneChazelas. Ei ei ei. tiedän jo, että
ls
on funktio. tiedän ettäls
-toimintoni kutsuuls
-kenttää osoitteestaPATH
. Nytwhich
kertoo minulle, missä tiedosto on. Näet vain yhden kertakäyttöisen tapauksen: ” Mitä kuorini tekisi tällä komennolla. ” Tässä käyttötapauksessawhich
on väärä, oikea.Mutta on muitakin käyttötapauksia, joissa (GNU)which
on täsmälleen oikea asia. - @rudimeter, riippuu
which
toteutus. Jotkut kertovat sinulle ’ s aliaksen (jos sinulla on määritetty alias tai jos kotonasi on~/.cshrc
kuten alias), jotkut antavat sinulle polun, mutta väärän tietyissä olosuhteissa.sh -c 'command -v ls'
, vaikka se ei olekaan täydellinen, antaa sinulle todennäköisesti oikean vastauksen erilaisiin vaatimuksiin (ja on myös vakio).
Vastaa
Yksi asia, josta (pikakäynnistyksestäni) näyttää siltä, että Stephane ei maininnut, on se, että which
on ei ole aavistustakaan shellisi polun hash-taulukosta. Tällä on vaikutusta siihen, että se saattaa palauttaa tuloksen, joka ei edusta suoritettua, mikä tekee siitä tehottoman virheenkorjauksessa.
Vastaa
Ripustan yleensä, kun tätä kysymystä suositellaan epäuskoisille käyttäjille, koska perusteeton which
-tukeminen ei ole hyödyllistä kenellekään.
Jos which
toimii hyvin ja antaa oikean vastauksen joihinkin tehtäviin Unix-moton mukaisesti: tee yksi asia, tee se hyvin , miksi which
olla kielletty?
Kysymyksen pitäisi siis olla, mikä toimii hyvin ja tekee tietyn työn hyvin?
Yhdelle ulkoinen apuohjelma osoitteessa / bin / joka Debianissa on shell-komentosarja, jonka tavoitteena on vain luetella tietyn nimen suoritettavat tiedostot polulle. Uskon, että which
tekee tarkoituksensa oikein. Se ei lataa mitään aliaksia, ei toimintoja, ei mitään komentotulkista, vaan vain listaa tietyn nimen ensimmäiset (tai kaikki) suoritettavat tiedostot PATH: iin. mikä tarkoittaa , että käyttäjä on löytänyt saman nimisen tiedoston, on käyttäjän (hänen) selvitettävä asia itse.
Kyllä, muilla which
toteutuksilla voi olla (ja yleensä onkin) tiettyjä ongelmia.
Vastaa
Kuulemme usein sitä, jota tulisi välttää. Miksi? Mitä meidän pitäisi käyttää sen sijaan?
En ole koskaan kuullut sitä. Anna tarkkoja esimerkkejä. Olen huolissani Linux-jakelustasi ja asennetuista ohjelmistopaketeistasi, koska sieltä which
tulee!
SLES 11.4 x86-64
tcsh-versiossa 6.18.01:
> which which which: shell built-in command.
bash-versiossa 3.2-147:
> which which /usr/bin/which > which -v GNU which v2.19, Copyright (C) 1999 - 2008 Carlo Wood. GNU which comes with ABSOLUTELY NO WARRANTY; This program is free software; your freedom to use, change and distribute this program is protected by the GPL.
which
on osa util-linux vakiopaketti, jonka Linux Kernel Organization jakelee käytettäväksi osana Linux-käyttöjärjestelmää. Se tarjoaa myös nämä muut tiedostot
/bin/dmesg /bin/findmnt /bin/logger /bin/lsblk /bin/more /bin/mount /bin/umount /sbin/adjtimex /sbin/agetty /sbin/blkid /sbin/blockdev /sbin/cfdisk /sbin/chcpu /sbin/ctrlaltdel /sbin/elvtune /sbin/fdisk /sbin/findfs /sbin/fsck /sbin/fsck.cramfs /sbin/fsck.minix /sbin/fsfreeze /sbin/fstrim /sbin/hwclock /sbin/losetup /sbin/mkfs /sbin/mkfs.bfs /sbin/mkfs.cramfs /sbin/mkfs.minix /sbin/mkswap /sbin/nologin /sbin/pivot_root /sbin/raw /sbin/sfdisk /sbin/swaplabel /sbin/swapoff /sbin/swapon /sbin/switch_root /sbin/wipefs /usr/bin/cal /usr/bin/chrp-addnote /usr/bin/chrt /usr/bin/col /usr/bin/colcrt /usr/bin/colrm /usr/bin/column /usr/bin/cytune /usr/bin/ddate /usr/bin/fallocate /usr/bin/flock /usr/bin/getopt /usr/bin/hexdump /usr/bin/i386 /usr/bin/ionice /usr/bin/ipcmk /usr/bin/ipcrm /usr/bin/ipcs /usr/bin/isosize /usr/bin/line /usr/bin/linux32 /usr/bin/linux64 /usr/bin/look /usr/bin/lscpu /usr/bin/mcookie /usr/bin/mesg /usr/bin/mkzimage_cmdline /usr/bin/namei /usr/bin/rename /usr/bin/renice /usr/bin/rev /usr/bin/script /usr/bin/scriptreplay /usr/bin/setarch /usr/bin/setsid /usr/bin/setterm /usr/bin/tailf /usr/bin/taskset /usr/bin/time /usr/bin/ul /usr/bin/uname26 /usr/bin/unshare /usr/bin/uuidgen /usr/bin/wall /usr/bin/whereis /usr/bin/which /usr/bin/write /usr/bin/x86_64 /usr/sbin/addpart /usr/sbin/delpart /usr/sbin/fdformat /usr/sbin/flushb /usr/sbin/freeramdisk /usr/sbin/klogconsole /usr/sbin/ldattach /usr/sbin/partx /usr/sbin/rcraw /usr/sbin/readprofile /usr/sbin/rtcwake /usr/sbin/setctsid /usr/sbin/tunelp
minun util-linux
on versio 2.19. Julkaisutiedot löytyvät helposti v2.13: sta (päivätty 28. elokuuta 2007). Etkö ole varma, mikä tämän päämäärä tai tavoite oli, siihen ei varmasti vastattu tuossa pidenneessä äänessä 331 kertaa.
Kommentit
- Huomaa, kuinka kysymyksessä ei mainita, mihin Unixiin se viittaa. Linux on vain yksi harvoista.
- Kuten
which -v
osoittaa, että ’ on GNU, joka (ylimääräinen) toinen mainitaan toisessa vastauksessa eikä se ole mitenkään spesifinen Linuxille), ei util-linux, johon AFAIK ei koskaan sisällyttänytwhich
-apuohjelmaa. util-linux 2.19 on vuodelta 2011, GNU, joka 2.19 on vuodelta 2008.
which
-käyttöä, ovat interaktiivisen kuoren kontekstin. Tämä kysymys on merkitty / siirrettävyys. Joten tulkitsen kysymys tässä kontekstissa nimellä ” mitä käyttääwhich
: n sijasta etsimään tietyn nimen ensimmäinen suoritettava tiedosto kohdasta$PATH
”. Useimmat vastaukset ja syyt vastaanwhich
käsittelevät aliaksia, sisäänrakennettuja tiedostoja ja toimintoja, joista useimmissa reaalimaailman kannettavissa komentotiedostosarjoissa on vain akateemista merkitystä. Paikallisesti määriteltyjä aliaksia ei ’ t peritä, kun suoritetaan komentosarjakomentosarja (ellet lähde sitä.
).csh
(jawhich
on edelleen komentocsh
useimmissa kaupallisissa kohteissa Unices) lukee~/.cshrc
, kun se ei ole vuorovaikutteinen. Siksi ’ s, miksi ’ ll huomaa csh-komentosarjat alkavat yleensä#! /bin/csh -f
.which
ei, koska se pyrkii antamaan sinulle aliaksia, koska se ’ on tarkoitettu työkaluksicsh
(vuorovaikutteiset) käyttäjät. POSIX-kuorien käyttäjillä oncommand -v
.(t)csh
(tai et ’ ole mielessä, jos se ei anna ’ t antaa sinulle oikean tuloksen), käytätype
taicommand -v
sen sijaan . Katso vastaukset miksi .stat $(which ls)
on väärä useista syistä (puuttuu--
, lainausmerkit puuttuvat), ei pelkästäänwhich
). ’ käytätstat -- "$(command -v ls)"
. Tämä olettaa, ettäls
on todellakin tiedostojärjestelmästä löydetty komento (ei kuoren sisäänrakennettu osa tai aliaksen toiminto).which
saattaa antaa sinulle väärän polun (ei polun, jonka komentotulkki suorittaa, jos syötätls
) tai antaa sinulle määritetyn aliaksen joidenkin muiden kuorien kokoonpanossa …which
-toteutukset eivät antaisi sinulle edesls
, joka löydetään hakemalla$PATH
(riippumatta siitä, mitäls
voi vedota kuoressasi).sh -c 'command -v ls'
taizsh -c 'rpm -q --whatprovides =ls'
antaa todennäköisemmin oikean vastauksen. Tässä on se, ettäwhich
on rikki perintö, joka on peräisincsh
.