Når du leder efter stien til en eksekverbar eller kontrollerer, hvad der ville ske, hvis du indtaster et kommandonavn i en Unix-shell, er der en overflod af forskellige hjælpeprogrammer ( which, type, command, whence, where, whereis, whatis, hash osv.).
Vi hører ofte, at which bør undgås. Hvorfor? Hvad skal vi bruge i stedet?
Kommentarer
Svar
Her er alt, hvad du aldrig troede, du aldrig ville have lyst til at vide om det:
Oversigt
For at få stienavn på en eksekverbar i et Bourne-lignende shell-script (der er et par advarsler; se nedenfor):
ls=$(command -v ls)
For at finde ud af om der findes en given kommando:
if command -v given-command > /dev/null 2>&1; then echo given-command is available else echo given-command is not available fi
Ved prompt af en interaktiv Bourne-lignende shell:
type ls
The which -kommandoen er en ødelagt arv fra C-Shell og er bedre alene i Bourne-lignende skaller.
Brug sager
Der “en sondring mellem at kigge efter disse oplysninger som en del af et script eller interaktivt på shellprompten.
Ved shellprompten er den typiske brugssag: denne kommando opfører sig underligt, bruger jeg rigtig? Hvad skete der nøjagtigt, da jeg skrev mycmd? Kan jeg se nærmere på, hvad det er?
I så fald vil du vide, hvad din shell gør, når du påberåber sig kommandoen uden faktisk at påberåbe sig kommandoen.
I shell-scripts har det en tendens til at være helt anderledes. I et shell-script er der ingen grund til, at du vil vide, hvor eller hvad en kommando er, hvis alt hvad du vil gøre er at køre den. Generelt er det, du vil vide, stien til den eksekverbare, så du kan få mere information ud af den (som stien til en anden fil i forhold til den, eller læse oplysninger fra indholdet af den eksekverbare fil på den sti).
Interaktivt vil du måske vide om alle my-cmd kommandoer, der er tilgængelige på systemet, i scripts, sjældent.
De fleste af de tilgængelige værktøjer (som det ofte er tilfældet) er designet til at blive brugt interaktivt.
Historie
Først en smule historie.
De tidlige Unix-skaller indtil slutningen af 70erne havde ingen funktioner eller aliaser. Kun den traditionelle sletning af eksekverbare filer i $PATH. csh introducerede alias omkring 1978 (skønt csh først blev frigivet i 2BSD, i maj 1979), og også behandlingen af en .cshrc for brugerne til at tilpasse shell (hver shell, som csh , læser .cshrc selv når det ikke er interaktivt som i scripts).
Mens Bourne-skallen først blev frigivet i Unix V7 tidligere i 1979, blev funktionssupport kun tilføjet meget senere (1984 i SVR2), og alligevel havde den aldrig noget rc fil (.profile er til at konfigurere dit miljø, ikke skallen per se ).
csh blev meget mere populær end Bourne-skallen, da (selvom den havde en frygtelig dårligere syntaks end Bourne shell) tilføjede en masse mere praktiske og pæne funktioner til interaktiv brug.
I 3BSD (1980), en which csh-script blev tilføjet til csh -brugerne for at hjælpe med at identificere en eksekverbar, og det er et næppe andet script, du kan finde som which på mange kommercielle enheder i dag (som Solaris, HP / UX, AIX eller Tru64).
Dette script læser brugeren” s ~/.cshrc (som alle csh scripts gør, medmindre de påkaldes med csh -f) og ser de angivne kommandonavne op på listen over aliasser og i $path (det array, som csh opretholder baseret på $PATH).
Here you go: which kom først efter den mest populære shell på det tidspunkt (og csh var stadig populær indtil midten af 90erne), hvilket er hovedårsagen til, at det blev dokumenteret i bøger og stadig bruges i vid udstrækning.
Bemærk, at selv for en csh -bruger, at which csh-script giver dig ikke nødvendigvis de rigtige oplysninger. Det får de aliasser, der er defineret i ~/.cshrc, ikke dem, du måske har defineret senere ved prompten eller for eksempel ved source ved en anden csh fil, og (selvom det ikke ville være en god idé), kan PATH muligvis omdefineres i ~/.cshrc.
At køre den which -kommando fra en Bourne-shell vil stadig slå aliasser op, der er defineret i din ~/.cshrc hvis du ikke har en, fordi du ikke bruger csh, ville det sandsynligvis stadig give dig det rigtige svar.
En lignende funktionalitet blev ikke tilføjet til Bourne-skallen indtil 1984 i SVR2 med type indbygget kommando. Det faktum, at det er indbygget (i modsætning til et eksternt script) betyder, at det kan give dig de rigtige oplysninger (til en vis grad), da det har adgang til skallenes indre.
Den oprindelige type kommando led af et lignende problem som which scriptet, idet det ikke returnerede en status for fejlafslutning, hvis kommandoen blev ikke fundet. For eksekverbare filer, i modsætning til which, udsender den noget som ls is /bin/ls i stedet for bare /bin/ls hvilket gjorde det mindre let at bruge i scripts.
Unix version 8″ s (ikke frigivet i naturen) Bourne-shell havde det “s type indbygget omdøbt til whatis. Og Plan9 (en gang efterfølger til Unix) skal rc (og dens derivater som akanga og es) har også whatis.
Korn-skallen (en delmængde, hvoraf POSIX sh definition er baseret på), udviklet i midten af 80erne, men ikke bredt tilgængelig før 1988, tilføjede mange af csh -funktionerne ( line editor, aliaser …) oven på Bourne shell. Det tilføjede sin egen whence builtin (ud over type), som tog flere muligheder (-v for at give type -lignende verbose output og -p for kun at se efter eksekverbare filer (ikke aliaser / funktioner …)) .
Tilfældig med uroen med hensyn til ophavsretsspørgsmål mellem AT & T og Berkeley, kom der et par gratis software shellimplementeringer ud i slutningen af 80erne begyndelsen af 90erne.Hele Almquist-skallen (ash, som erstatning for Bourne-skallen i BSDer), implementeringen af det offentlige domæne af ksh (pdksh), bash (sponsoreret af FSF), zsh kom ud mellem 1989 og 1991.
Ash, selvom det var meningen at være en erstatning for Bourne-skallen, havde ikke en type indbygget indtil meget senere (i NetBSD 1.3 og FreeBSD 2.3 ), selvom det havde hash -v. OSF / 1 /bin/sh havde en type som altid returnerede 0 op til OSF / 1 v3.x. bash tilføjede ikke en whence men tilføjede en -p mulighed for at type for at udskrive stien (type -p ville være som whence -p) og -a for at rapportere alle de matchende kommandoer. tcsh lavede which indbygget og tilføjede en where kommando, der fungerer som bash” s type -a. zsh har dem alle.
fish shell (2005) har en type -kommando implementeret som en funktion.
which csh-script blev i mellemtiden fjernet fra NetBSD (da det var indbygget i tcsh og ikke meget brug i andre skaller), og funktionaliteten blev føjet til whereis (når påkaldt som which, whereis opfører sig som which bortset fra at den kun ser på eksekverbare filer i iv id = “00879d7bee” I OpenBSD og FreeBSD blev which også ændret til en skrevet i C, der kun ser kommandoer i $PATH .
Implementeringer
Der er snesevis af implementeringer af en which co mmog på forskellige enheder med forskellig syntaks og adfærd.
På Linux (ved siden af de indbyggede i tcsh og zsh ) vi finder flere implementeringer. På for nylig Debian-systemer er det “et simpelt POSIX-shell-script, der ser efter kommandoer i $PATH.
busybox har også en which kommando.
Der er en GNU which som sandsynligvis er den mest ekstravagante. Den forsøger at udvide, hvad which csh-scriptet gjorde til andre skaller: du kan fortælle det, hvad dine aliaser og funktioner er, så det kan give dig et bedre svar (og jeg tror, at nogle Linux-distributioner angiver nogle globale aliaser omkring det for bash for at gøre det).
zsh har et par operatorer til at udvide til stien til eksekverbare filer: operatøren = filnavnudvidelse og :c historieudvidelsesmodifikator (her anvendt på parameterudvidelse ):
$ print -r -- =ls /bin/ls $ cmd=ls; print -r -- $cmd:c /bin/ls
zsh, i -modul gør også kommandot hash-tabellen som commands associativ matrix:
$ print -r -- $commands[ls] /bin/ls
whatis -værktøjet (undtagen den i Unix V8 Bourne-skal eller Plan 9 rc / es) er ikke rigtig relateret, da det kun er til dokumentation (greps whatis-databasen, det vil sige manopsidens “).
whereis var også tilføjet i 3BSD på samme tid som which selvom det blev skrevet i C, ikke csh og bruges til at slå op på samme tid, den eksekverbare, man-side og kilde, men ikke baseret på det aktuelle miljø. Så igen svarer det på et andet behov.
Nu på standardfronten specificerer POSIX command -v og -V kommandoer (som tidligere var valgfri indtil POSIX.2008). UNIX angiver kommandoen type (ingen mulighed). At “s alle (where, which, whence er ikke angivet i nogen standard) .
Op til en eller anden version var type og command -v valgfri i Linux Standard Base-specifikationen, hvilket forklarer hvorfor nogle gamle versioner af posh (dog baseret på pdksh, som begge havde begge), havde heller ikke nogen. command -v blev også føjet til nogle Bourne shell-implementeringer (som på Solaris).
Status i dag
Status i dag er, at type og command -v er allestedsnærværende de Bourne-lignende skaller (dog som bemærket af @jarno skal du bemærke advarslen / bugten i bash når de ikke er i POSIX-tilstand eller nogle efterkommere af Almquist-skallen nedenfor i kommentarer). tcsh er den eneste skal, hvor du vil bruge which (da der ikke er noget type der og which er indbygget).
I andre skaller end tcsh og zsh, which fortæller dig muligvis stien til den givne eksekverbare, så længe der ikke er noget alias eller funktion med det samme navn i nogen af vores ~/.cshrc, ~/.bashrc eller en hvilken som helst shell-startfil, og du definerer ikke $PATH i din ~/.cshrc. Hvis du har defineret et alias eller en funktion til det, fortæller det dig måske ikke eller fortæller dig den forkerte ting.
Hvis du vil vide det om alle kommandoerne med et givet navn er der intet bærbart. Du ville bruge where i tcsh eller zsh, type -a i bash eller zsh, whence -a i ksh93 og i andre skaller , kan du bruge type i kombination med which -a som muligvis fungerer.
Anbefalinger
At få stienavnet til en eksekverbar
For at få stienavnet til en eksekverbar i et script er der et par advarsler:
ls=$(command -v ls)
ville være den standard måde at gøre det på.
Der er dog nogle få problemer:
- Det er ikke muligt at kende stien til den eksekverbare uden at udføre den.
type,which,command -v… alle bruger heuristik til at finde ud af stien De løber gennem$PATH-komponenterne og finder den første ikke-biblioteksfil, som du har tilladelse til. Dog depe nding på skallen, når det kommer til udførelse af kommandoen, vil mange af dem (Bourne, AT & T ksh, zsh, ash …) bare udføre dem i rækkefølgen af$PATHindtilexecvesystemopkald vender ikke tilbage med en fejl. For eksempel, hvis$PATHindeholder/foo:/bar, og du vil udførels, prøver de først at udføre/foo/lseller hvis det mislykkes/bar/ls. Nu kan udførelse af/foo/lsmuligvis mislykkes, fordi du ikke har eksekveringstilladelse, men også af mange andre grunde, da det ikke er en gyldig eksekverbar.command -v lsrapporterer/foo/lshvis du har eksekveringstilladelse til/foo/ls, men kørerlskører muligvis/bar/lshvis/foo/lsikke er en gyldig eksekverbar fil. - hvis
fooer en indbygget funktion eller et alias, returnerercommand -v foofoo. Med nogle skaller somash,pdkshellerzsh, kan det også returnerefoohvis$PATHinkluderer den tomme streng, og der er en eksekverbarfoo-fil i den aktuelle mappe. Der er nogle omstændigheder, hvor du muligvis skal tage det i betragtning. Husk for eksempel, at listen over indbyggede varierer med implementeringen af shell (for eksempel ermountundertiden indbygget til optaget bokssh), og f.eks.bashkan få funktioner fra miljøet. - hvis
$PATHindeholder relative stykomponenter (typisk.eller den tomme streng, som begge henviser til den aktuelle mappe, men som muligvis kan være hvad som helst), afhængigt af skallen,command -v cmdudsender muligvis ikke en absolut sti. Så den sti, du opnår på det tidspunkt, du kører er ikke længere gyldig, efter at ducdet andet sted. - Anekdotisk: med ksh93-skallen, hvis
/opt/ast/bin(selvom den nøjagtige sti kan variere på forskellige systemer, tror jeg) er i dig$PATH, ksh93 vil stille et par ekstra indbyggede til rådighed (chmod,cmp,cat…), mencommand -v chmodreturnerer/opt/ast/bin/chmod, selvom stien ikke findes.
Bestemmelse af, om der findes en kommando
For at finde ud af, om en given kommando eksisterer som standard, kan du gøre:
if command -v given-command > /dev/null 2>&1; then echo given-command is available else echo given-command is not available fi
Hvor man måske vil bruge which
(t)csh
I csh og tcsh har du ikke meget valg. I tcsh er det “s fint som which er indbygget. I csh er det kommandoen which, som muligvis ikke gør hvad du vil i nogle få tilfælde.
Find kun kommandoer i nogle skaller
Et tilfælde, hvor det kan være fornuftigt at bruge which er, hvis du vil kende stien til en kommando og ignorere potentialet shell-indbyggede funktioner i bash, csh (ikke tcsh), dash eller Bourne shell-scripts, det vil sige skaller, der ikke har whence -p = “cd104fd905”>
ellerzsh),command -ev(somyash),whatis -p(rc,akanga) eller en indbyggetwhich(somtcshellerzsh) på systemer, hvorwhichtilgængelig og er ikkecshscript.
Hvis disse betingelser er opfyldt, vil:
echo=$(which echo)
give dig stien til den første echo i $PATH (undtagen i hjørnetilfælde), uanset om echo også tilfældigvis er en shell indbygget / alias / funktion eller ej.
I andre skaller foretrækker du:
- zsh :
echo==echoellerecho=$commands[echo]ellerecho=${${:-echo}:c} - ksh , zsh :
echo=$(whence -p echo) - yash :
echo=$(command -ev echo) - rc , akanga :
echo=`whatis -p echo`(pas på stier med mellemrum) - fisk :
set echo (type -fp echo)
Bemærk, at hvis alt hvad du vil gøre er kør at echo kommando, du behøver ikke at få sin sti, du kan bare gøre:
env echo this is not echoed by the builtin echo
For eksempel med tcsh for at forhindre, at det indbyggede which bruges:
set Echo = "`env which echo`"
Når du har brug for en ekstern kommando
Et andet tilfælde, hvor du måske vil bruge which, er når du faktisk har brug for en ekstern kommando. POSIX kræver, at alle shell-indbyggede (som command) også er tilgængelige som eksterne kommandoer, men desværre er det ikke tilfældet for command på mange systemer. For eksempel er det sjældent at finde en command kommando på Linux-baserede operativsystemer, mens de fleste af dem har en which kommando (dog forskellige med forskellige indstillinger og adfærd).
Tilfælde, hvor du muligvis vil have en ekstern kommando, vil være overalt, hvor du udfører en kommando uden at påkalde en POSIX-shell.
system("some command line"), popen() … funktioner på C eller forskellige sprog påkalder en shell for at analysere kommandolinjen, så system("command -v my-cmd") arbejder i dem. En undtagelse derfra ville være perl, som optimerer skallen, hvis den ikke ser noget shell-specialtegn (bortset fra mellemrum). Det gælder også dens backtick-operatør:
$ 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
Tilføjelsen af den :; ovenfor tvinger perl til at påkalde en shell der. Ved at bruge which behøver du ikke bruge det trick.
Kommentarer
- @Joe,
whicher etcshscript på mange kommercielle enheder. Årsagen er historisk, at ‘ hvorfor jeg gav historien, så folk forstår, hvor den kom fra, hvorfor folk blev vant til at bruge den, og hvorfor der faktisk ‘ er ingen grund til at bruge det. Og ja, nogle mennesker bruger (t) csh. Ikke alle bruger Linux endnu - Efter at have læst dette indlæg har jeg fundet en masse kontekst til svaret, men ikke selve svaret.Hvor i dette indlæg siger det faktisk ikke at bruge
whichi modsætning til ting, du måske prøver at brugewhichat gøre, historien omwhich, implementeringer afwhich, andre kommandoer til at udføre relaterede opgaver eller grunde til faktisk at brugewhich? Hvorfor er de andre kommandoer bedre ? Hvad gør de anderledes endwhich? Hvordan undgår de faldgruber? Dette svar bruger faktisk flere ord på problemerne med alternativerne end problemerne medwhich. -
commander beskrevet af POSIX. - @St é phaneChazelas Hvis jeg opretter en ny fil med
touch /usr/bin/mytestfileog kør dereftercommand -v mytestfile, det giver stien (hvorimodwhich mytestfileikke). - @jarno, åh ja, du ‘ har ret.
bashvil slå sig ned på en ikke-eksekverbar fil, hvis den ‘ ikke kan finde en eksekverbar fil, så den ‘ s ” OK ” (selvom man i praksis hellere vilcommand -v/typereturnerer en fejl) som at ‘ er kommandoen, den vil prøve at udføre, når du kørermytestfile, mendashadfærd er ujævn, som om der ‘ er en ikke-eksekverbarcmdforan en eksekverbar encommand -vreturnerer den ikke-eksekverbare, mens udførelse afcmdville udføre den eksekverbare (den forkerte man er også hash). FreeBSDsh(også baseret påash) har den samme fejl. zsh, yash, ksh, mksh, bash som sh er OK.
Svar
Årsagerne til, at man kan ikke ønsker at bruge which er allerede blevet forklaret, men her er et par eksempler på et par systemer, hvor which faktisk fejler.
På Bourne-lignende skaller sammenligner vi output fra which med output fra type (type er en shell-indbygget, menes det at være grundens sandhed, da det er skallen, der fortæller os, hvordan det vil påberåbe sig en kommando).
Mange tilfælde er hjørne sager, men husk at which / type ofte bruges i hjørnesager (for at finde svaret til en uventet opførsel som: hvorfor i alverden opfører den kommando sig sådan, hvilken kalder jeg på? ).
De fleste systemer, de fleste Bourne-lignende skaller: funktioner
Det mest oplagte tilfælde er for funktioner:
$ type ls ls is a function ls () { [ -t 1 ] && set -- -F "$@"; command ls "$@" } $ which ls /bin/ls
Årsagen er, at which kun rapporterer om eksekverbare filer og nogle gange om aliaser (dog ikke altid dem fra din shell), ikke om funktioner.
Den GNU, som man-siden har brudt (da de glemte at citere $@) eksempel på, hvordan man også bruger den til at rapportere funktioner, men ligesom for aliaser, fordi den ikke implementerer en shell-syntaks-parser, narre den let:
$ 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; }
De fleste systemer, mest Bourne-lignende skaller: builtins
Et andet indlysende tilfælde er indbyggede eller nøgleord, da which at være en ekstern kommando ikke har nogen måde at vide, hvilke indbyggede din shell har (og nogle skaller som zsh, bash eller ksh kan indlæse buildins dynamisk):
$ 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
(det gælder ikke for zsh hvor which er indbygget)
Solaris 10, AIX 7.1, HP / UX 11i, Tru64 5. 1 og mange andre:
$ 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
Dette skyldes, at de fleste kommercielle enheder which (som i den oprindelige implementering på 3BSD) er et csh script, der læser ~/.cshrc. De aliasser, den rapporterer, er dem, der er defineret der uanset de aliasser, du i øjeblikket har defineret, og uanset den shell, du rent faktisk bruger.
I HP / UX eller Tru64:
% echo "setenv PATH /bin:/usr/bin" >> ~/.cshrc % setenv PATH ~/bin:/bin:/usr/bin % ln -s /bin/ls ~/bin/ % which ls /bin/ls
(Solaris- og AIX-versionerne har løst problemet ved at gemme $path før du læser ~/.cshrc og gendanne det, før du slår kommandoen (e) op)
$ 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
Eller:
$ 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
(selvfølgelig, da du er et csh script, kan du ikke forvente, at det fungerer med argumenter, der indeholder mellemrum …)
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="
På dette system er der et alias-defineret system-bredt, der omslutter GNU which -kommandoen.
Den falske output skyldes, at which læser output fra bash “s alias men ved ikke, hvordan man analyserer det ordentligt og bruger heuristik (et alias pr. linje, ser efter den første fundne kommando efter en |, ;, & …)
Det værste ved CentOS er, at zsh har en perfekt fin which indbygget kommando, men CentOS formåede at bryde den ved at erstatte den med et ikke-fungerende alias til GNU which.
Debian 7.0, ksh93:
(dog gælder de fleste systemer med mange skaller)
$ unset PATH $ which which /usr/local/bin/which $ type which which is a tracked alias for /bin/which
På Debian, /bin/which er et /bin/sh script. I mit tilfælde er sh dash men det er det samme, når det “s bash.
En ikke-indstillet PATH er ikke til at deaktivere PATH opslag, men betyder at bruge systemet “s standard PATH som desværre på Debian ikke er enig i (dash og bash har /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin, zsh har /bin:/usr/bin:/usr/ucb:/usr/local/bin, ksh93 har /bin:/usr/bin, mksh har /usr/bin:/bin ($(getconf PATH)), execvp() (som i env) har :/bin:/usr/bin (ja, ser først i den aktuelle mappe!)) .
Derfor får which det forkert ovenfor, da det bruger dash “s standard PATH som er forskellig fra ksh93 “s
Det er nej t bedre med GNU which som rapporterer:
which: no which in ((null))
(interessant er der faktisk en /usr/local/bin/which på mit system, som faktisk er et akanga script, der fulgte med akanga (et rc shell-derivat, hvor standard PATH er /usr/ucb:/usr/bin:/bin:.))
bash, ethvert system:
Den Chris henviser til i sit svar :
$ 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
Også efter at have ringet til hash manuelt:
$ 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)
Nu er det tilfældet, hvor which og undertiden type mislykkes:
$ 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
Nu med nogle skaller:
$ foo bash: ./b/foo: /: bad interpreter: Permission denied
Med andre:
$ foo a/foo
Hverken which eller type kan på forhånd vide, at b/foo ikke kan b e udført. Nogle skaller som bash, ksh eller yash, når de påkalder foo vil faktisk prøve at køre b/foo og rapportere en fejl, mens andre (som zsh, ash, csh, Bourne, tcsh) kører a/foo ved fejl i execve() systemkald b/foo.
Kommentarer
-
mkshbruger faktisk noget andet til standard$PATH: først , bruges operativsystemets kompileringstidskonstant_PATH_DEFPATH(oftest på BSDer), derefter anvendesconfstr(_CS_PATH, …)(POSIX), og hvis begge ikke findes eller mislykkes, bruges/bin:/usr/bin:/sbin:/usr/sbin. - I dit 1. eksempel, selvom
lser en funktion, den bruges i glsfra PATH. Ogwhicher fint at fortælle dig, hvilken der bruges/usr/bin/lseller/usr/local/bin/ls. Jeg ser ikke ‘ ” Hvorfor ikke bruge hvilken ” …. - @rudimeier, At
which lsgiver mig/bin/lsuanset omlsfunktion kalder/bin/lseller/opt/gnu/bin/lsellerdireller slet ingenting. IOW,which(det, som implementeringer, IMMV) giver noget irrelevant - @St é phaneChazelas. Nej Nej Nej. Jeg ved allerede, at min
lser en funktion. Jeg ved at minlsfunktion kalderlsfraPATH. Nu fortællerwhichmig, hvor filen er. Du ser kun en enkelt brugssag: ” Hvad ville min shell gøre med denne kommando. ” Til denne brugssagwhicher forkert, korrekt.Men der er andre brugstilfælde, hvor (GNU)whicher nøjagtigt den rigtige ting. - @rudimeter afhænger af
whichimplementering. Nogle vil fortælle dig, at det ‘ er et alias (hvis du har et alias konfigureret, eller hvis der er et~/.cshrci dit hjem, der har sådan et alias), nogle vil give dig en vej, men den forkerte under visse betingelser.sh -c 'command -v ls', selvom det ikke er perfekt, er det stadig mere sandsynligt, at det giver dig det rigtige svar på det forskellige krav (og er også standard).
Svar
En ting, som (fra mit hurtige skum) ser ud til, at Stephane ikke nævnte, er at which har ingen idé om din shell “sti-hash-tabel. Dette har den virkning, at det muligvis returnerer et resultat, der ikke er repræsentativt for det, der faktisk køres, hvilket gør det ineffektivt i fejlfinding.
Svar
Jeg krymper normalt, når dette spørgsmål anbefales til intetanende brugere, fordi grundløs bashing på which ikke er nyttig for nogen.
Hvis which fungerer godt og giver det rigtige svar på en eller anden opgave ved at følge Unix-motoen: gør en ting, gør det godt hvorfor skal which være forbudt?
Spørgsmålet skal så være, hvilken der fungerer godt og gør et specifikt job godt?
For det ene er det eksterne værktøj ved / bin / hvilket i Debian er et shell-script, hvis mål kun er at angive eksekverbare filer med det givne navn på stien. Jeg tror, at which gør sit tilsigtede mål korrekt. Den indlæser ingen aliaser, ingen funktioner, intet fra skallen, lister bare de første (eller alle) eksekverbare filer af det givne navn på PATH. betyder for at have fundet en fil med samme navn som givet er noget, som brugeren skal finde ud af af hende (ham) selv.
Ja, andre which implementeringer kan (og har normalt) særlige problemer.
Svar
Vi hører ofte, hvad der skal undgås. Hvorfor? Hvad skal vi bruge i stedet?
Det har jeg aldrig hørt. Angiv specifikke eksempler. Jeg ville bekymre mig om din linux-distribution og installerede softwarepakker, for det er det sted, hvor which kommer fra!
SLES 11.4 x86-64
i tcsh version 6.18.01:
> which which which: shell built-in command.
i bash-version 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 er en del af util-linux en standardpakke distribueret af Linux Kernel Organization til brug som en del af Linux-operativsystemet. Det giver også disse andre filer
/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
min util-linux er version 2.19. Udgivelsesnoter kan let findes tilbage til v2.13 dateret (28. august 2007). Ikke sikker på hvad pointen eller målet med dette var, det blev bestemt ikke besvaret i den lange ting, der blev opstemt 331 gange.
Kommentarer
- Bemærk hvordan spørgsmål nævnes ikke, hvad Unix det henviser til. Linux er blot et af få.
- Som din
which -vviser, at ‘ s GNU som (det ekstravagante en nævnt i det andet svar og er på ingen måde specifik for Linux), ikke util-linux, som AFAIK aldrig inkluderede etwhich-værktøj. util-linux 2.19 er fra 2011, GNU som 2.19 er fra 2008.
whichantager en interaktiv shell-kontekst. Dette spørgsmål er tagget / bærbarhed. Så jeg fortolker spørgsmålet i denne sammenhæng som ” hvad man skal bruge i stedet forwhichtil at finde den første eksekverbare fil af et givet navn i$PATH“. De fleste svar og grunde imodwhichbeskæftiger sig med aliaser, indbyggede funktioner og funktioner, som i de fleste bærbare shell-scripts fra den virkelige verden bare er af akademisk interesse. Lokalt definerede aliasser arves ikke ‘ t, når du kører et shell-script (medmindre du kilder det til.).csh(ogwhicher stadig etcshscript på de fleste kommercielle Unices) læser~/.cshrcnår de ikke er interaktive. At ‘ hvorfor du ‘ bemærker, at csh-scripts normalt starter med#! /bin/csh -f.whichikke fordi det sigter at give dig aliaserne, fordi det ‘ er ment som et værktøj til (interaktive) brugere afcsh. Brugere af POSIX-skaller harcommand -v.(t)csh(eller hvis du ikke ‘ ikke har noget imod det, hvis det ikke ‘ ikke giver dig det rigtige resultat), brugtypeellercommand -vi stedet . Se svarene til hvorfor .stat $(which ls)er forkert af flere årsager (mangler--, manglende anførselstegn), ikke kun brugen afwhich). Du ‘ brugerstat -- "$(command -v ls)". Det antager, atlsfaktisk er en kommando, der findes på filsystemet (ikke en indbygget i din shell eller aliasfunktion).whichkan give dig den forkerte sti (ikke den sti, som din shell ville udføre, hvis du indtastedels) eller give dig et alias som defineret i konfigurationen af nogle andre skaller …whichimplementeringer ikke ville give dig enganglsder ville blive fundet ved et opslag af$PATH(uanset hvadlskan påberåbe sig i din skal).sh -c 'command -v ls'ellerzsh -c 'rpm -q --whatprovides =ls'er mere tilbøjelige til at give dig det rigtige svar. Pointen her er, atwhicher en brudt arv fracsh.