Miért ne használná a “ alkalmazást, amely ”? Mit használjunk akkor?

Amikor egy futtatható fájl elérési útját keresi, vagy ellenőrzi, mi történne, ha a parancs nevét beírja a Unix héjba, rengeteg különféle segédprogram található ( which, type, command, whence, where, whereis, whatis, hash, stb.).

Gyakran halljuk, hogy a which -t el kell kerülni. Miért? Mit használjunk helyette?

Megjegyzések

  • Úgy gondolom, hogy a (z) which használatával szembeni legtöbb érv interaktív shell-kontextust feltételez. Ez a kérdés tagged / hordozhatóság. Tehát értelmezem a kérdés ebben az összefüggésben ” néven mit használjon a which helyett egy adott név első futtatható fájljának megtalálásához a $PATH “. A legtöbb válasz és indok which álnevekkel, beépítettekkel és függvényekkel foglalkozik, amelyek a legtöbb valós hordozható shell szkriptben csak tudományos érdeklődésre tartanak számot. A helyileg definiált álnevek nem ‘ t öröklődnek egy shell parancsfájl futtatásakor (hacsak nem a . címmel állítja be).
  • @MattBianco, igen, csh (és which továbbra is csh szkript a legtöbb reklámban Unices) beolvassa ~/.cshrc, ha nem interaktív. Ezért ‘ ezért ‘ észreveszi, hogy a csh szkriptek általában #! /bin/csh -f -vel kezdődnek. A which nem azért van, mert célja az álnevek megadása, mert ‘ eszközként szolgál A (z) csh (interaktív) felhasználói. A POSIX héjfelhasználók command -v.
  • @rudimeier, akkor a válasz mindig lesz, hacsak a héja nem (t)csh (vagy nem bánja, ha ‘ nem adja meg a helyes eredményt), használja a type vagy command -v helyett . Nézze meg a miért válaszokat.
  • @rudimeier, (

több okból is téves (hiányzik a--, hiányzó idézőjelek), nemcsak awhichhasználata. ‘ használhatja astat -- "$(command -v ls)"alkalmazást. Ez feltételezi, hogy alsvalóban a fájlrendszeren található parancs (nem a shell beépített része vagy az alias funkciója). Awhichhibás elérési utat adhat meg (nem azt az utat, amelyet a héj végrehajtana, ha beírja als), vagy a megadott alias-t adja meg néhány más héj konfigurációjában …

  • @rudimeier, megint számos olyan feltétel van, amelyek mellett sok which megvalósítás még a ls, amelyet a $PATH keresésével találhatunk meg (függetlenül attól, hogy mi ls hívhat a héjában). A sh -c 'command -v ls' vagy a zsh -c 'rpm -q --whatprovides =ls' nagyobb valószínűséggel adja meg a helyes választ. A lényeg itt az, hogy a which a csh törött öröksége.
  • Válasz

    Itt minden, amit soha nem gondolt, hogy soha nem akar tudni erről:

    Összegzés

    A egy Bourne-szerű shell szkript futtatható fájljának elérési útja (néhány megjegyzés található; lásd alább):

    ls=$(command -v ls) 

    Annak kiderítése, hogy létezik-e egy adott parancs:

    if command -v given-command > /dev/null 2>&1; then echo given-command is available else echo given-command is not available fi 

    Egy interaktív Bourne-szerű shell parancsára:

    type ls 

    A which parancs a C-Shell törött öröksége, és jobb, ha egyedül marad a Bourne-szerű héjakban.

    Esetek használata

    Ott “Megkülönböztethető az információ keresése egy szkript részeként vagy interaktív módon a shell parancssorban.

    A shell parancssorban a tipikus használati eset a következő: ez a parancs furcsán viselkedik, használom a igaz? Mi történt pontosan, amikor beírtam a következőt: mycmd? Megnézhetem tovább, mi ez?

    Ebben az esetben tudni szeretné, hogy mit csinál a héja, amikor a parancs tényleges meghívása nélkül hívja meg a parancsot.

    A shell szkriptekben általában egészen más. Egy shell szkriptben nincs ok arra, hogy miért akarod tudni, hogy hol vagy mi a parancs, ha csak azt akarod végrehajtani. Általában azt akarja tudni, hogy a futtatható fájl elérési útja, így több információt hozhat ki belőle (például egy másik fájl elérési útját ehhez képest, vagy információkat olvashat a futtatható fájl tartalmából ezen az útvonalon).

    Interaktív módon érdemes tudni a rendszeren elérhető my-cmd parancsok összes ről, parancsfájlokban, ritkán.

    A rendelkezésre álló eszközök többségét (ahogy az gyakran előfordul) interaktív használatra tervezték.

    Előzmények

    Először egy kis előzmény.

    A korai Unix héjak a 70-es évek végéig nem voltak funkciók vagy álnevek. Csak a futtatható fájlok hagyományos keresése a $PATH fájlban. A csh álneveket 1978 körül vezetett be (bár csh először kiadták a 2BSD, 1979 májusában), valamint egy .cshrc feldolgozása a felhasználók számára a héj testreszabásához (minden héj, mint csh , a .cshrc szöveget olvassa el, még akkor is, ha nem interaktív, mint a szkripteknél.) később (1984 az SVR2-ben), és egyébként sem volt soha rc fájl (a .profile a környezet konfigurálása, nem a shell önmagában ).

    csh sokkal népszerűbb lett, mint a Bourne-héj, mivel (bár a szintaxisa szörnyen rosszabb volt, mint a Bourne shell) sokkal kényelmesebb és kellemesebb funkciókat adott az interaktív használathoz.

    A 3BSD (1980) cikkben >

    whichcsh szkriptet adtak hozzá acshfelhasználók számára, hogy segítsenek egy futtatható fájl azonosításában, és “alig különbözõ szkriptet találsz, amelywhichmanapság számos kereskedelmi egységen (például Solaris, HP / UX, AIX vagy Tru64).

    Ez a szkript beolvassa a felhasználó” s ~/.cshrc (mint az összes csh szkript, hacsak nem hívják meg csh -f -vel), és megkeresi a megadott parancsneveket az álnevek és a $path (a csh által fenntartott tömb a $PATH alapján).

    Tessék: which az első helyet érte el az akkori legnépszerűbb héjnál (és a csh még a közepéig népszerű volt. 90-es évek), ami a fő ok, amiért dokumentálták a könyvekben, és továbbra is széles körben használják.

    Ne feledje, hogy még csh felhasználó esetében is az a which csh szkript nem feltétlenül adja meg a megfelelő információkat. Megkapja a ~/.cshrc fájlban definiált álneveket, nem pedig azokat, amelyeket később a parancssorban, vagy például source másik csh fájlt, és (bár ez nem lenne jó ötlet), PATH lehet, hogy újradefiniálják a ~/.cshrc.

    A which parancs futtatása egy Bourne-héjból továbbra is a ~/.cshrc -ben megadott álneveket keresi, de ha nincs ilyen, mert nem használja a csh szolgáltatást, akkor valószínűleg még mindig a megfelelő választ kapná.

    Hasonló funkciót nem adtak hozzá a Bourne-héj 1984-ig az SVR2-ben a type beépített paranccsal. Az a tény, hogy beépített (szemben egy külső szkriptel) azt jelenti, hogy tud adni (bizonyos mértékben) megfelelő információkat, mivel hozzáfér a héj belső részéhez.

    A kezdeti type parancs hasonló problémát szenvedett, mint a which parancsfájl, mivel nem adta vissza a hiba kilépési állapotát, ha A parancs nem található. Ezenkívül a futtatható fájlok esetében, ellentétben a which -vel, a ls is /bin/ls -hez hasonló értéket ad ki a ami megkönnyítette a szkriptekben való használatát.

    A Unix 8-as verziójú (vadon nem kiadott) Bourne-héj” s type builtin átnevezve whatis -re. És a Plan9 (a Unix egyszeri utódja) shell rc (és annak olyan származékok, mint akanga és es) whatis is vannak.

    A Korn héj (amelynek részhalmaza a A 80-as évek közepén kifejlesztett, de 1988 előtt nem széles körben elérhető POSIX sh definíción alapszik) sok csh funkciót ( vonalszerkesztő, álnevek …) a Bourne-héj tetején. Hozzáadta a saját whence beépített részét (az type mellett), amely több lehetőséget is igénybe vett (-v a type -szerű verbózus kimenettel, és -p csak futtatható fájlok keresésére (nem álnevek / függvények …)) .

    Az AT & T és Berkeley közötti szerzői jogi kérdésekkel kapcsolatos zűrzavar egyidejűleg néhány ingyenes szoftver héj implementáció következett a 80-as évek végén, a 90-es évek elején.Az összes Almquist héj (ash, amely a Bourne-héj cseréje a BSD-kben), a ksh (pdksh), bash (az FSF támogatása), zsh 1989 és 1991.

    Ash, bár a Bourne-héj helyettesítésére szánta, csak később volt type beépítve (a NetBSD 1.3-ban és a FreeBSD 2.3-ban) ), bár hash -v volt benne. Az OSF / 1 /bin/sh beépített type volt, 0-t adott vissza az OSF / 1 v3.x-re. bash nem adott hozzá whence -t, de hozzáadott egy -p opció a type lehetőségre az útvonal kinyomtatásához (type -p olyan lenne, mint whence -p) és -a a megfelelő parancsok összes jelentéséhez. tcsh which beépítettet készített, és hozzáadott egy where parancsot, amely úgy működik, mint bash” s type -a. zsh mindegyik megvan.

    A fish shell (2005) type parancsot hajtott végre függvényként.

    A which a csh szkriptet időközben eltávolították a NetBSD-ből (mivel a tcsh-ben építették be, és más kagylóban nem sokat használtak), és a funkcionalitás hozzáadódott a whereis fájlhoz (amikor which, whereis úgy viselkedik, mint which, azzal a különbséggel, hogy csak a ). Az OpenBSD-ben és a FreeBSD-ben a which szintén C-re írtra változott, és csak $PATH .

    Megvalósítások

    Tucatnyi megvalósítás létezik egy which co mmand különféle szintaxisú és viselkedésű Unice-okon.

    Linuxon (a beépítettek mellett a tcsh és zsh ) számos megvalósítást találunk. A legújabb Debian rendszereken például “egy egyszerű POSIX shell parancsfájl, amely parancsokat keres a $PATH fájlban.

    busybox rendelkezik egy which paranccsal is.

    Van egy GNU which, amely valószínűleg a leg extravagánsabb. Megpróbálja kiterjeszteni a which csh parancsfájl más héjakra is: elmondhatja neki, hogy mik az álnevei és funkciói, hogy megadhassa jobb választ adsz neked (és úgy gondolom, hogy egyes Linux disztribúciók bizonyos globális álneveket állítanak köré a bash számára).

    zsh van pár operátora , amely kibővíthető a futtatható fájlok elérési útjára: a = fájlnévbővítés operátor és a :c előzménybővítő módosító (itt a paraméterbővítés re vonatkozik):

    $ print -r -- =ls /bin/ls $ cmd=ls; print -r -- $cmd:c /bin/ls 

    zsh, a modul a parancs hash tábláját is létrehozza commands asszociatív tömbként:

    $ print -r -- $commands[ls] /bin/ls 

    A whatis segédprogram (kivéve a Unix V8 Bourne-héjban vagy a 9. tervben szereplő rc / es) valójában nem kapcsolódik, mivel csak dokumentációra szolgál (megkapja a whatis adatbázist, vagyis a man oldal szinopszisát).

    whereis szintén hozzáadva a 3BSD fájlba egyidejűleg a which fájlba, bár C -ban írták, csh és egyszerre keresésre, a futtatható fájlra, a man oldalra és a forrásra használják, de nem az aktuális környezet alapján. Tehát megint ez válaszol egy másik igényre.

    Most a POSIX a szokásos fronton megadja a command -v és -V parancsok (amelyek korábban POSIX 2008-ig nem kötelezőek voltak). A UNIX megadja a type parancsot (nincs opció). Ez az összes (where, which, whence nincs meghatározva egyetlen szabványban sem) .

    Bizonyos verziókig a type és a command -v opcionális volt a Linux Standard Base specifikációban, ami megmagyarázza, miért Például a (z) posh néhány régi verziója (bár a pdksh alapján mindkettő volt) egyikének sem volt. command -v is hozzá lett adva néhány Bourne shell-implementációhoz (például a Solaris-hoz).

    Állapot ma

    Manapság az az állapot, hogy type és command -v mindenütt mindenütt jelen van a Bourne-szerű héjak (bár, amint azt @jarno megjegyezte, vegye figyelembe a figyelmeztetést / hibát bash -ben, ha nincs POSIX módban, vagy az Almquist shell néhány leszármazottját a megjegyzésekben). A tcsh az egyetlen héj, ahová a which -t szeretné használni (mivel nincsenek type ott van, és which be van építve).

    A tcsh és , which megmondhatja az adott futtatható fájl elérési útját, mindaddig, amíg ~/.cshrc, ~/.bashrc vagy bármelyik shell indítófájl, és nem definiálja a $PATH elemet a

    . Ha definiál egy álnevet vagy funkciót, akkor lehet, hogy elárulja, vagy nem, vagy rosszat mond.

    Ha tudni akarod az összes megadott néven futó parancsról nincs semmi hordozható. Használja a where elemet a tcsh vagy zsh, bash vagy zsh, whence -a a ksh93-ban és más héjakban , használhatja az type -t az which -a vel kombinálva, amelyek működhetnek.

    Ajánlások

    A futtatható fájl elérési útjának megszerzése

    A futtatható fájl elérési útjának megszerzéséhez egy szkriptben van néhány figyelmeztetés:

    ls=$(command -v ls) 

    lenne a szokásos módja ennek.

    Ennek ellenére van néhány probléma:

    • Nem lehet tudni a futtatható fájl útvonalát végrehajtás nélkül. a type, which, command -v … mindegyik heurisztikát használ az út megtalálásához . Végiglépnek a $PATH összetevőkön, és megtalálják az első nem könyvtárfájlt, amelyre engedélyt ad. A parancs végrehajtásakor a parancsértelmezőn sokan közülük (Bourne, AT & T ksh, zsh, ash …) csak végrehajtják őket a sorrendben. $PATH, amíg a execve rendszerhívás nem tér vissza hibával. Például, ha a $PATH /foo:/bar -t tartalmaz, és szeretné végrehajtani a ls parancsot, akkor először megpróbálják /foo/ls végrehajtásához, vagy ha ez nem sikerül /bar/ls. A /foo/ls végrehajtása sikertelen lehet, mert nem rendelkezik végrehajtási engedéllyel, hanem sok más okból is, például nem érvényes futtatható fájlként. command -v ls jelenteni fogja /foo/ls, ha rendelkezik végrehajtási engedéllyel a /foo/ls fájlhoz, de fut a ls valóban futhat /bar/ls, ha a /foo/ls nem érvényes futtatható.
    • ha a foo beépített vagy függvény vagy álnév, akkor command -v foo visszatér a következőhöz: foo. Néhány olyan héjnál, mint ash, pdksh vagy zsh, visszatérhet a foo ha a $PATH tartalmazza az üres karakterláncot, és van egy futtatható foo fájl az aktuális könyvtárban. Vannak olyan esetek, amikor ezt figyelembe kell vennie. Ne feledje például, hogy a beépítettek listája a shell implementációjától függően változik (például mount néha beépített a busybox számára sh), és például bash funkciókat kaphat a környezettől.
    • ha relatív útvonalkomponenseket tartalmaz (általában . vagy az üres karakterláncot, amelyek mind az aktuális könyvtárra utalnak, de bármi lehetnek), a héjtól függően, command -v cmd lehet, hogy nem ad ki abszolút elérési utat. Tehát az útvonal, amelyet a többé nem lesz érvényes, miután cd valahol máshol volt.
    • Anekdotikus: a ksh93 héjjal, ha /opt/ast/bin (bár ez a pontos elérési út eltérhet a különböző rendszerektől, úgy gondolom) benned van $PATH, a ksh93 elérhetővé teszi néhány extra beépített programot (chmod, cmp, cat …), de command -v chmod akkor is visszatér /opt/ast/bin/chmod, ha az elérési út nem létezik.

    A parancs létezésének meghatározása

    Ha meg szeretné tudni, hogy egy adott parancs létezik-e szabványosan, akkor tegye a következőket:

    if command -v given-command > /dev/null 2>&1; then echo given-command is available else echo given-command is not available fi 

    Ahol érdemes használni a which

    (t)csh

    A csh és tcsh csoportokban nincs sok választási lehetősége. A tcsh mezőben ez “rendben van, mivel which beépítve van. A csh fájlban ez lesz a rendszer which parancs, amely néhány esetben nem biztos, hogy azt teszi, amit akar.

    Parancsok keresése csak néhány héjban

    Előfordulhat, hogy van értelme a which használatának, ha meg akarja ismerni a parancs útját, figyelmen kívül hagyva a potenciált beépített shellek vagy a bash, csh (nem tcsh), dash vagy Bourne shell szkriptek, vagyis olyan héjak, amelyek nem rendelkeznek whence -p (például ksh vagy zsh), command -ev (például yash ), whatis -p (rc, akanga) vagy beépített which (például tcsh vagy zsh) olyan rendszereken, ahol which elérhető, és nem a csh szkript.

    Ha ezek a feltételek teljesülnek, akkor:

    echo=$(which echo) 

    megadná az első echo a $PATH -ban (a sarok esetek kivételével), függetlenül attól, hogy a echo is héj-e beépített / alias / function, vagy sem.

    Más héjakban inkább:

    • zsh : echo==echo vagy echo=$commands[echo] vagy echo=${${:-echo}:c}
    • ksh , zsh : echo=$(whence -p echo)
    • yash : echo=$(command -ev echo)
    • rc , akanga : echo=`whatis -p echo` (óvakodj a szóközökkel rendelkező utaktól)
    • hal : set echo (type -fp echo)

    Ne feledje, hogy ha csak annyit szeretne csinálni, akkor futtassa azt a echo parancsot, akkor nem kell elérnie az útvonalát, csak megteheti:

    env echo this is not echoed by the builtin echo 

    Például a tcsh paranccsal, hogy megakadályozza a beépített which használatát:

    set Echo = "`env which echo`" 

    Ha külső parancsra van szükség

    Egy másik eset, amikor érdemes használni a which alkalmazást, amikor valójában szüksége van egy külső parancs. A POSIX megköveteli, hogy az összes shell beépített program (például command) külső parancsként is elérhető legyen, de sajnos ez nem így van a command sok rendszeren. Például ritkán található command parancs Linux alapú operációs rendszereken, míg a legtöbbjüknek which parancs (bár különbözőek, különböző opciókkal és viselkedéssel).

    Azokban az esetekben, amikor külső parancsra van szükség, bárhová futtatnának egy parancsot POSIX héj meghívása nélkül.

    A system("some command line"), popen() … a C vagy különféle nyelvek függvényei héjat hívnak meg a parancssor elemzéséhez, ezért system("command -v my-cmd") munkát végeznek bennük. Ez alól kivételt jelentene az perl, amely optimalizálja a héjat, ha nem lát semmilyen shell speciális karaktert (a szóköz kivételével). Ez vonatkozik a backtick operátorára is:

    $ 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 

    A fenti :; hozzáadása perl parancsértelmező meghívására kényszeríti A which használatával nem kell ezt a trükköt használni.

    Megjegyzések

    • @Joe, which egy csh szkript számos kereskedelmi egységben. Az ok történelmi, hogy ‘ miért adtam át az előzményeket, hogy az emberek megértsék, honnan származik, miért szokták meg az emberek és miért is valójában ott vannak ‘ nincs ok arra, hogy használnod kell. És igen, egyesek a (t) csh-t használják. Még nem mindenki használja a Linuxot
    • A bejegyzés elolvasása után sok összefüggést találtam a válaszra, de nem magát a választ.Hol található ebben a bejegyzésben, miért nem használja a which -t, szemben olyan dolgokkal, amelyeket esetleg megpróbál használni which tennivaló, a which előzményei, a which megvalósításai, egyéb parancsok a kapcsolódó feladatok elvégzéséhez, vagy a tényleges használat okai which? Miért jobb a többi parancs jobb ? Mit csinálnak másképp, mint a which? Hogyan kerülhetik el a buktatókat? Ez a válasz valójában több szót fordít az alternatívák problémáira, mint a which problémáira.
    • command POSIX által.
    • @St é phaneChazelas Ha új fájlt hozok létre touch /usr/bin/mytestfile által, majd futtatom a command -v mytestfile, megadja az elérési utat (míg which mytestfile nem).
    • @jarno, igen, te ‘ igaza van. bash egy nem futtatható fájlra települ, ha ‘ nem talál futtatható fájlt, tehát ‘ s ” OK ” (bár a gyakorlatban inkább command -v / type hibát ad vissza), mivel ez a ‘ s az a parancs, amelyet megpróbál végrehajtani, amikor futtatja a , de a dash viselkedés hibás, mintha ‘ nem futtatható cmd egy futtatható előtt, command -v visszaadja a nem futtathatót, miközben a cmd futtatja a futtathatót (rossz az egyik is hash). A FreeBSD sh (szintén a ash alapján) ugyanaz a hiba. zsh, yash, ksh, mksh, bash as sh rendben vannak.

    Válasz

    Az okok nem akarja használni a which kifejezést már elmagyarázták, de íme néhány példa néhány olyan rendszerre, ahol a which valóban meghibásodik.

    Bourne-szerű héjakon összehasonlítjuk a which kimenetét a type (type mivel egy beépített héj, ez az alapigazság, mivel a héj megmondja nekünk, hogyan hívja meg a parancsot.

    Sok esetben corner esetek, de ne feledje, hogy which / type gyakran használják sarok esetekben (a válasz megtalálásához váratlan viselkedésre, például: miért a földön viselkedik ez a parancs így, melyiket hívom? ).

    A legtöbb rendszer, a legtöbb Bourne-szerű héj: funkciók

    A legkézenfekvőbb eset a függvényekre vonatkozik:

    $ type ls ls is a function ls () { [ -t 1 ] && set -- -F "$@"; command ls "$@" } $ which ls /bin/ls 

    Ennek az az oka, hogy a which csak a futtatható fájlokról és néha álnevekről (bár nem mindig a te héjadról) számol be, nem pedig funkciókról.

    Az a GNU, amelyik man oldalnak meghibásodott (mivel elfelejtették idézni az $@ idézetet) példa arra, hogyan kell használni a funkciók jelentésére is, de csakúgy, mint álnevek, mivel nem valósítja meg a shell szintaxis elemzőjét, ezért könnyen becsapja:

    $ 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; } 

    A legtöbb rendszer, a legtöbb Bourne-szerű shell: beépített

    Egy másik nyilvánvaló eset a beépített elemek vagy kulcsszavak, mivel a which külső parancs nem tudja tudni, hogy melyik beépített héja van a héjnak (és néhány olyan héj, mint a zsh, bash vagy ksh dinamikusan be tudja tölteni a beépítetteket):

    $ 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 

    (ez nem vonatkozik a zsh elemre, ahol which be van építve)

    Solaris 10, AIX 7.1, HP / UX 11i, Tru64 5. 1 és még sokan mások:

    $ 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 

    Ennek az az oka, hogy a legtöbb kereskedelmi egységben which (mint az eredeti megvalósításban) a 3BSD-n) egy csh parancsfájl, amely a következőt írja: ~/.cshrc. Az általa jelentett álnevek az ott definiált álnevek, függetlenül a jelenleg definiált álnevektől és a ténylegesen használt héjatól.

    HP / UX vagy Tru64 esetén:

    % echo "setenv PATH /bin:/usr/bin" >> ~/.cshrc % setenv PATH ~/bin:/bin:/usr/bin % ln -s /bin/ls ~/bin/ % which ls /bin/ls 

    (a Solaris és az AIX verzió kijavította ezt a problémát a $path mentésével, mielőtt elolvasta a ~/.cshrc és visszaállítása a parancs (ok) megkeresése előtt)

    $ 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 

    Vagy:

    $ 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 

    (természetesen csh parancsfájlként nem várhatjuk el, hogy szóközöket tartalmazó argumentumokkal működjön …)

    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=" 

    Ezen a rendszeren egy egész rendszerre definiált álnév van, amely beburkolja a GNU which parancsot.

    A hamis kimenet azért van, mert a which beolvassa a bash “s alias de nem tudja, hogyan kell megfelelően elemezni, és heurisztikát használ (soronként egy alias, az első megtalált parancsot keresi egy |, , & …)

    A CentOS legrosszabb dologja, hogy zsh egy teljesen finom which beépített parancs, de a CentOS sikerült megtörnie azzal, hogy egy nem működő aliasra cserélte GNU which.

    Debian 7.0, ksh93:

    (bár a legtöbb kagylóval rendelkező rendszerre vonatkozik)

    $ unset PATH $ which which /usr/local/bin/which $ type which which is a tracked alias for /bin/which 

    A Debianon /bin/which egy /bin/sh szkript. Az én esetemben sh dash, de ugyanaz, ha “s bash.

    Egy unset PATH nem az PATH keresés letiltása, hanem a “s alapértelmezett PATH amivel sajnos a Debianon senki sem ért egyet (dash és bash /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin, zsh /bin:/usr/bin:/usr/ucb:/usr/local/bin, ksh93 /bin:/usr/bin, mksh /usr/bin:/bin ($(getconf PATH)), execvp() (például env esetén) :/bin:/usr/bin (igen, először az aktuális könyvtárba néz!) .

    Éppen ezért which téveszti fent, mivel a dash alapértelmezett PATH amely eltér a ksh93 “s

    Ez nem jobb, ha a GNU which, amely beszámol:

    which: no which in ((null)) 

    (érdekes módon valóban van egy /usr/local/bin/which a rendszeremen, ami valójában egy akanga szkript, amely a akanga ( “>

    shell származék, ahol az alapértelmezettPATH/usr/ucb:/usr/bin:/bin:.)))

    bash, bármely rendszer:

    Az a Chris, akire válaszában hivatkozik :

    $ 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 

    A hash kézi hívás után is:

    $ 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) 

    Most olyan eset van, amikor which és néha type nem sikerül:

    $ 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 

    Most, néhány kagylóval:

    $ foo bash: ./b/foo: /: bad interpreter: Permission denied 

    Másokkal:

    $ foo a/foo 

    Sem which, sem type előre tudhatja, hogy b/foo nem tud b e kivégezték. Néhány héj, például bash, ksh vagy yash, amikor a foo valóban megpróbálja futtatni a b/foo -et és hibát jelenteni, míg mások (például zsh, ash, csh, Bourne, tcsh) futni fog a/foo a execve() rendszerhívás sikertelensége esetén a b/foo.

    Megjegyzések

    • mksh valójában mást használ az alapértelmezett $PATH esetén: először , az operációs rendszer fordítási időállandóját _PATH_DEFPATH használják (leggyakrabban a BSD-kön), majd confstr(_CS_PATH, …) (POSIX), és ha mindkettő nem létezik, vagy nem sikerül, akkor a /bin:/usr/bin:/sbin:/usr/sbin kifejezést használjuk.
    • Az első példában még akkor is, ha ls egy olyan függvény, amely usin g ls a PATH-ból. És a which jó, ha megmondja, melyiket használják /usr/bin/ls vagy /usr/local/bin/ls. Nem látom ‘ nem látom ” Miért ne használnám, melyik ” ….
    • @rudimeier, Ez az which ls /bin/ls nekem ad, függetlenül attól, hogy a ls függvényhívások /bin/ls vagy /opt/gnu/bin/ls vagy dir, vagy semmi. IOW, which (ami a megvalósításokat, az IMMV) valami irrelevánsat ad
    • @St é phaneChazelas. Nem nem nem. Már tudom , hogy a ls függvényem. tudom , hogy a ls függvényem ls -et hívja a következőtől: PATH. Most which megmondja, hol van a fájl. Csak egyetlen egyszer használatos esetet lát: ” Mit csinálna a shellem ezzel a paranccsal. ” Ehhez a felhasználási esethez which téves, helyes.De vannak más olyan felhasználási esetek is, amikor a (GNU) which pontosan a helyes dolog.
    • @rudimeter, a which megvalósítás. Néhányan elmondják, hogy ‘ álnév (ha van beállítva álnév, vagy ha van otthonában ~/.cshrc ilyen álnév), néhány megad egy utat, de bizonyos feltételek mellett rossz. sh -c 'command -v ls', bár nem tökéletes, mégis valószínűbb, hogy megfelelő választ ad erre a különböző követelményre (és ez szintén szabványos).

    Válasz

    Egy dolgot (a gyors átfutásom alapján) úgy tűnik, hogy Stephane nem említette, hogy which fogalmad sincs a héj elérési útjának hash táblájáról. Ez azt eredményezi, hogy olyan eredményt adhat vissza, amely nem reprezentatív a ténylegesen lefuttatottakhoz, ami hatástalanná teszi a hibakeresésben.

    Válasz

    Általában akkor összerándulok, amikor ezt a kérdést a gyanútlan felhasználóknak ajánljuk, mert a which alaptalan alapja senkinek sem hasznos.

    Ha jól működik, és helyes választ ad valamilyen feladatra, követve a Unix motívumát: csinálj egyet, csináld jól , miért kellene which be kell tiltani?

    Akkor kell feltenni a kérdést, hogy melyik működik jól, és jól teljesít-e egy adott munkát?

    Az egyik esetében a / bin / melyik külső segédprogram a Debianban egy shell szkript, amelynek célja csak a megadott név futtatható fájljainak felsorolása az útvonalon. Úgy gondolom, hogy a which helyesen teljesíti a kitűzött célt. Nem tölt be álneveket, funkciókat, semmit a shellből, csak felsorolja a PATH-ra az adott név első (vagy összes) futtatható fájlját. A jelentése, hogy a megadott névvel rendelkező fájlt talált, a felhasználónak neki (neki) kell kitalálnia önálló.

    Igen, más which megvalósításoknak lehetnek (és általában vannak) sajátos problémáik.

    Válasz

    Gyakran halljuk, amit el kell kerülni. Miért? Mit használjunk helyette?

    Ezt még soha nem hallottam. Kérjük, adjon meg konkrét példákat. Aggódnék a Linux disztribúciód és a telepített szoftvercsomagjaid miatt, mivel innen származik a which!

    SLES 11.4 x86-64

    tcsh 6.18.01 verzióban:

    > which which which: shell built-in command. 

    a bash 3.2-147 verzióban:

    > 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 a util-linux a Linux Kernel Organization által forgalmazott szabványos csomag, amely a Linux operációs rendszer részeként használható. Ezeket a többi fájlokat is biztosítja.

    /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 

    az én util-linux a 2.19-es verzió. A kiadási megjegyzések könnyen megtalálhatók a 2007. augusztus 28-i verzióig. Nem biztos benne, mi volt ennek a célja vagy célja, és biztosan nem válaszoltak arra a hosszadalmas dologra, amely 331 alkalommal adott szavazatot.

    Hozzászólások

    • Vegye észre, hogy a kérdés nem tesz említést arról, hogy mire hivatkozik a Unix. A Linux csak egy a néhány közül.
    • Amint a which -v fájlja mutatja, az a ‘ GNU, amely (az extravagáns az egyiket a másik válaszban említettem, és semmiképpen sem jellemző a Linuxra), nem a util-linux, amelyhez az AFAIK soha nem tartalmazott which segédprogramot. A util-linux 2.19 2011-ből származik, a GNU pedig 2.19-ből áll.

    Vélemény, hozzászólás?

    Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük