Patrząc na ścieżce do pliku wykonywalnego lub sprawdzanie, co by się stało, jeśli wpiszesz nazwę polecenia w powłoce Unix, istnieje mnóstwo różnych mediów ( which
, type
, command
, whence
, where
, whereis
, whatis
, hash
, etc).
Często słyszymy, że which
należy tego unikać. Dlaczego? Czego powinniśmy użyć zamiast tego?
shell
history
which
portability
Stéphane Chazelas
źródło
źródło
which
zakłada interaktywny kontekst powłoki. To pytanie jest oznaczone / przenośne. Tak więc interpretuję pytanie w tym kontekście jako „czego użyć zamiastwhich
znaleźć pierwszy plik wykonywalny danej nazwy w$PATH
”. Większość odpowiedzi i powodówwhich
przemawiających przeciwko aliasom, wbudowanym funkcjom i funkcjom, które w większości przenośnych skryptów powłoki w świecie rzeczywistym są przedmiotem zainteresowania akademickiego. Lokalnie zdefiniowane aliasy nie są dziedziczone podczas uruchamiania skryptu powłoki (chyba że zostanie to za pomocą źródła.
).csh
(iwhich
nadal jestcsh
skryptem na większości komercyjnych Unices) czyta,~/.cshrc
gdy nie jest interaktywny. Dlatego zauważysz, że skrypty csh zwykle zaczynają się od#! /bin/csh -f
.which
nie robi tego, ponieważ ma na celu udostępnienie aliasów, ponieważ ma służyć jako narzędzie dla (interaktywnych) użytkownikówcsh
. Użytkownicy powłok POSIXcommand -v
.(t)csh
(lub nie masz nic przeciwko, jeśli nie da ci poprawnego wyniku), użyjtype
lubcommand -v
zamiast tego . Zobacz odpowiedzi na pytanie dlaczego .stat $(which ls)
jest niepoprawny z kilku powodów (brakujące--
, brakujące cytaty), nie tylko użyciewhich
). Użyłbyśstat -- "$(command -v ls)"
. Zakładals
się, że rzeczywiście jest to polecenie znalezione w systemie plików (nie wbudowane w powłokę ani funkcję aliasu).which
może dać ci niewłaściwą ścieżkę (nie ścieżkę, którą wykonałaby twoja powłoka, gdybyś wszedłls
) lub dać alias zdefiniowany w konfiguracji niektórych innych powłok ...which
implementacji nie dałoby ci nawet tychls
, które można by znaleźć podczas wyszukiwania$PATH
(niezależnie od tego, cols
może wywołać w twojej powłoce).sh -c 'command -v ls'
lubzsh -c 'rpm -q --whatprovides =ls'
częściej udzielają prawidłowej odpowiedzi. Chodzi o to, żewhich
jest to zepsute dziedzictwocsh
.Odpowiedzi:
Oto wszystko, o czym nigdy nie pomyślałeś, że nigdy nie chcesz o tym wiedzieć:
Podsumowanie
Aby uzyskać nazwę ścieżki pliku wykonywalnego w skrypcie powłoki podobnym do Bourne'a (jest kilka zastrzeżeń; patrz poniżej):
Aby dowiedzieć się, czy dane polecenie istnieje:
Po zachęcie interaktywnej powłoki podobnej do Bourne'a:
Ta
which
komenda jest zepsutym dziedzictwem z C-Shell i lepiej zostawić ją samą w muszlach podobnych do Bourne'a.Przypadków użycia
Istnieje rozróżnienie między wyszukiwaniem tych informacji jako części skryptu lub interaktywnym po zachęcie powłoki.
W wierszu poleceń typowym przypadkiem użycia jest: to polecenie zachowuje się dziwnie, czy używam właściwego? Co dokładnie się stało, kiedy pisałem
mycmd
? Czy mogę przyjrzeć się temu, co to jest?W takim przypadku chcesz wiedzieć, co robi twoja powłoka, kiedy wywołujesz polecenie bez faktycznego wywoływania polecenia.
W skryptach powłoki wygląda to zupełnie inaczej. W skrypcie powłoki nie ma powodu, dla którego chciałbyś wiedzieć, gdzie lub czym jest polecenie, jeśli wszystko, co chcesz zrobić, to uruchomić je. Ogólnie rzecz biorąc, chcesz wiedzieć o ścieżce pliku wykonywalnego, dzięki czemu możesz uzyskać więcej informacji (np. Ścieżkę do innego pliku w stosunku do tego lub odczytać informacje z zawartości pliku wykonywalnego przy tej ścieżce).
Interaktywnie, może chcesz wiedzieć o wszystkich tych
my-cmd
poleceń dostępnych w systemie, w skryptach, rzadko tak.Większość dostępnych narzędzi (jak to często bywa) została zaprojektowana do interaktywnego używania.
Historia
Najpierw trochę historii.
Wczesne powłoki uniksowe do późnych lat 70. nie miały żadnych funkcji ani aliasów. Tylko tradycyjne wyszukiwanie plików wykonywalnych w
$PATH
.csh
wprowadzono aliasy około 1978 r. (chociażcsh
po raz pierwszy wydano w2BSD
maju 1979 r.), a także przetwarzanie.cshrc
dla użytkowników w celu dostosowania powłoki (każda powłoka, jakcsh
czyta się,.cshrc
nawet jeśli nie jest interaktywna, jak w skryptach).natomiast Bourne shell został po raz pierwszy wydany w Unix V7 wcześniej w 1979 roku, wsparcie funkcja została tylko dodaje dużo później (1984 w SVR2), a w każdym razie, nigdy nie miałem jakiś
rc
plik (.profile
jest do skonfigurowania środowiska, nie powłoce per se ).csh
zyskał znacznie większą popularność niż powłoka Bourne'a, ponieważ (choć miał strasznie gorszą składnię niż powłoka Bourne'a), dodawał wiele wygodniejszych i przyjemniejszych funkcji do interaktywnego użytku.W
3BSD
(1980) dodanowhich
skrypt csh dlacsh
użytkowników, aby pomóc zidentyfikować plik wykonywalny, i jest to prawie inny skrypt, jaki można obecnie znaleźćwhich
w wielu komercyjnych Unices (takich jak Solaris, HP / UX, AIX lub Tru64).Ten skrypt odczytuje użytkownika
~/.cshrc
(tak jak wszystkiecsh
skrypty, chyba że jest wywoływanycsh -f
) i wyszukuje podane nazwy poleceń na liście aliasów i$path
(w tablicy, któracsh
utrzymuje się na podstawie$PATH
).Proszę bardzo,
which
w tym czasie pojawiła się pierwsza najpopularniejsza powłoka (icsh
była popularna do połowy lat 90.), co jest głównym powodem, dla którego została udokumentowana w książkach i jest nadal szeroko stosowana.Zauważ, że nawet dla
csh
użytkownika tenwhich
skrypt csh niekoniecznie dostarcza ci właściwych informacji. Pobiera zdefiniowane aliasy~/.cshrc
, a nie te, które mogłeś zdefiniować później w monicie lub na przykład poprzez umieszczeniesource
innegocsh
pliku, i (choć nie byłoby to dobrym pomysłem)PATH
może zostać ponownie zdefiniowane~/.cshrc
.Uruchomienie tego
which
polecenia z powłoki Bourne'a nadal szukałoby aliasów zdefiniowanych w twoim~/.cshrc
, ale jeśli nie masz takiego, ponieważ go nie używaszcsh
, prawdopodobnie nadal dostaniesz właściwą odpowiedź.Podobna funkcjonalność została dodana do powłoki Bourne'a dopiero w 1984 roku w SVR2 z
type
wbudowanym poleceniem. Fakt, że jest on wbudowany (w przeciwieństwie do zewnętrznego skryptu) oznacza, że może on dostarczyć odpowiednich informacji (do pewnego stopnia), ponieważ ma dostęp do wewnętrznych elementów powłoki.Początkowa
type
komenda napotkała podobny problem jakwhich
skrypt, ponieważ nie zwróciła statusu wyjścia błędu, jeśli komenda nie została znaleziona. Ponadto w przypadku plików wykonywalnych, w przeciwieństwie dowhich
tego, wypisuje coś podobnegols is /bin/ls
zamiast tego,/bin/ls
co czyni go łatwiejszym w użyciu w skryptach.Uniksowa wersja 8 (nie wydana na wolności) Powłoka Bourne'a, której
type
nazwa wbudowana została zmieniona nawhatis
. Powłoka Plan9 (niegdyś następca Uniksa)rc
(i jej pochodne jakakanga
ies
) również mająwhatis
.Powłoka Korna (podzbiór, na którym opiera się definicja sh POSIX), opracowana w połowie lat 80., ale nie szeroko dostępna przed 1988 r., Dodała wiele
csh
funkcji (edytor linii, aliasy ...) na wierzchu powłoki Bourne'a . Dodał własnewhence
wbudowane (oprócztype
), które wzięło kilka opcji (-v
aby zapewnićtype
pełne, podobne wyjście, i-p
szukać tylko plików wykonywalnych (nie aliasów / funkcji ...).Zbieg okoliczności w związku z zawirowaniami dotyczącymi praw autorskich między AT&T i Berkeley, kilka implementacji powłoki wolnego oprogramowania pojawiło się pod koniec lat 80. na początku lat 90. Cała skorupa Almquista (jesion, która ma zastąpić powłokę Bourne'a w BSD), publiczna implementacja ksh (pdksh)
bash
(sponsorowana przez FSF),zsh
pojawiła się w latach 1989-1991.Ash, choć miał być zamiennikiem powłoki Bourne'a, nie miał
type
wbudowanej wersji dużo później (w NetBSD 1.3 i FreeBSD 2.3), chociaż tak byłohash -v
. OSF / 1/bin/sh
miałtype
wbudowane narzędzie, które zawsze zwracało 0 do OSF / 1 v3.x.bash
nie dodał,whence
ale dodał-p
opcjętype
drukowania ścieżki (type -p
byłoby jakwhence -p
) i-a
zgłaszania wszystkich pasujących poleceń.tcsh
wykonanywhich
wbudowane i dodajewhere
polecenie działając jakbash
„stype -a
.zsh
ma je wszystkie.fish
Shell (2005) matype
polecenia realizowane jako funkcja.which
Csh skrypt tymczasem został usunięty z NetBSD (jak to było wbudowane w tcsh i nie wiele wykorzystania w innych powłok) oraz funkcjonalność dodana dowhereis
(gdy wywołany jakowhich
,whereis
zachowuje sięwhich
poza tym, że tylko wyszukuje pliki wykonywalne w$PATH
). W OpenBSD i FreeBSDwhich
zmieniono również na jeden napisany w C, który wyszukuje tylko polecenia$PATH
.Realizacje
Istnieją dziesiątki implementacji
which
polecenia na różnych Uniksach o różnej składni i zachowaniu.W systemie Linux (oprócz wbudowanych w
tcsh
izsh
) znajdujemy kilka implementacji. Na przykład w najnowszych systemach Debian jest to prosty skrypt powłoki POSIX, który szuka poleceń w$PATH
.busybox
ma równieżwhich
polecenie.Jest taki,
GNU
which
który jest prawdopodobnie najbardziej ekstrawagancki. Próbuje rozszerzyć to, cowhich
skrypt csh zrobił na inne powłoki: możesz powiedzieć, jakie są twoje aliasy i funkcje, aby dać ci lepszą odpowiedź (i wierzę, że niektóre dystrybucje Linuksa ustawiają wokół tego globalne aliasybash
) .zsh
ma kilka operatorów do rozszerzenia ścieżki do plików wykonywalnych: operator=
rozwijania nazw plików i:c
modyfikator rozszerzania historii (tutaj stosowany do rozszerzania parametrów ):zsh
, wzsh/parameters
module tworzy również tablicę skrótów poleceń jakocommands
tablicę asocjacyjną:whatis
Gospodarczy (z wyjątkiem jednego w Unix V8 Bourne shell lub planu 9rc
/es
) tak naprawdę nie jest związane, jak to tylko dokumentacja (greps bazę whatis, że jest człowiekiem strona streszczenie).whereis
został również dodany w3BSD
tym samym czasie,which
jakby został napisanyC
,csh
a nie służy do wyszukiwania w tym samym czasie pliku wykonywalnego, strony podręcznika i źródła, ale nie w oparciu o bieżące środowisko. Znów odpowiada to na inną potrzebę.Teraz, na standardowym froncie, POSIX określa polecenia
command -v
i-V
(które były opcjonalne do POSIX.2008). UNIX określatype
polecenie (brak opcji). To wszystko (where
,which
,whence
nie są określone w dowolnym standardzie)Do niektórych wersji
type
icommand -v
były opcjonalne w specyfikacji Linux Standard Base, która wyjaśnia, dlaczego na przykład niektóre stare wersjeposh
(choć oparte napdksh
których miały obie) nie miały żadnej z nich.command -v
został również dodany do niektórych implementacji powłoki Bourne'a (takich jak Solaris).Status dzisiaj
Obecnie status jest taki
type
icommand -v
są one wszechobecne we wszystkich powłokach podobnych do Bourne'a (jednak, jak zauważył @jarno, zwróć uwagę na zastrzeżenie / błąd,bash
gdy nie jest w trybie POSIX lub niektórzy potomkowie powłoki Almquist poniżej w komentarzach).tcsh
jest jedyną powłoką, w której chciałbyś użyćwhich
(ponieważ jej nietype
ma iwhich
jest wbudowana).W muszli innych niż
tcsh
izsh
,which
można powiedzieć, ścieżkę danego pliku wykonywalnego, tak długo jak nie ma pseudonim lub funkcja o tej samej nazwie, w każdym z naszych~/.cshrc
,~/.bashrc
lub dowolny plik startowy powłoki i nie określają$PATH
w twojej~/.cshrc
. Jeśli masz dla niego zdefiniowany alias lub funkcję, może ci o tym powiedzieć lub nie, lub powiedzieć coś niewłaściwego.Jeśli chcesz wiedzieć o wszystkich poleceniach pod danym imieniem, nie ma nic przenośnego. Można by użyć
where
wtcsh
lubzsh
,type -a
wbash
lubzsh
,whence -a
w ksh93 i innych skorup, można używaćtype
w połączeniu zwhich -a
których mogą pracować.Rekomendacje
Uzyskiwanie nazwy ścieżki do pliku wykonywalnego
Teraz, aby uzyskać ścieżkę do pliku wykonywalnego w skrypcie, istnieje kilka zastrzeżeń:
byłby to standardowy sposób na zrobienie tego.
Istnieje jednak kilka problemów:
type
,which
,command -v
... wszystkie heurystyki użytku, aby dowiedzieć się ścieżki. Przechodzą przez$PATH
komponenty i znajdują pierwszy plik inny niż katalog, dla którego masz uprawnienia do wykonania. Jednak w zależności od powłoki, jeśli chodzi o wykonanie polecenia, wiele z nich (Bourne, AT&T ksh, zsh, ash ...) po prostu wykona je w kolejności,$PATH
dopókiexecve
wywołanie systemowe nie powróci z błędem . Na przykład, jeśli$PATH
zawiera/foo:/bar
i chcesz wykonaćls
, najpierw spróbują wykonać/foo/ls
lub jeśli to się nie powiedzie/bar/ls
. Teraz wykonanie/foo/ls
może się nie powieść, ponieważ nie masz uprawnień do wykonywania, ale także z wielu innych powodów, np. nie jest to prawidłowy plik wykonywalny.command -v ls
zgłosi,/foo/ls
jeśli masz uprawnienia do wykonywania/foo/ls
, ale uruchomieniels
może faktycznie działać,/bar/ls
jeśli/foo/ls
nie jest prawidłowym plikiem wykonywalnym.foo
jest wbudowaną funkcją lub aliasem,command -v foo
zwracafoo
. Przy czym niektóre muszle podobaash
,pdksh
czyzsh
może również wrócićfoo
jeśli$PATH
zawiera pusty ciąg i jest wykonywalnyfoo
plik w bieżącym katalogu. Istnieją pewne okoliczności, w których może to być konieczne. Pamiętaj na przykład, że lista wbudowanych elementów różni się w zależności od implementacji powłoki (na przykładmount
czasami jest wbudowana dla busyboksash
) i na przykładbash
może pobierać funkcje ze środowiska.$PATH
zawiera względne komponenty ścieżki (zazwyczaj.
lub pusty ciąg, które oba odnoszą się do bieżącego katalogu, ale mogą być czymkolwiek), w zależności od powłoki,command -v cmd
może nie generować ścieżki bezwzględnej. Tak więc ścieżka, którą uzyskasz w czasie biegucommand -v
, nie będzie już ważna po tobiecd
gdzie indziej./opt/ast/bin
(choć że dokładna ścieżka może być różna w różnych systemach wierzę) jest w was$PATH
, ksh93 udostępni kilka dodatkowych builtins (chmod
,cmp
,cat
...), alecommand -v chmod
wróci/opt/ast/bin/chmod
nawet jeśli ścieżka robi” istnieje.Ustalanie, czy polecenie istnieje
Aby dowiedzieć się, czy dane polecenie istnieje standardowo, możesz:
Gdzie można chcieć użyć
which
(t)csh
W
csh
itcsh
nie masz dużego wyboru. Wtcsh
jest w porządku, jakwhich
jest wbudowane. Wcsh
będzie towhich
polecenie systemowe , które może nie zrobić tego, co chcesz w kilku przypadkach.znajdź polecenia tylko w niektórych powłokach
Przypadek, w którym może ona sensu używać
which
jest, jeśli chcesz poznać ścieżkę polecenia, pomijając potencjalne poleceń wbudowanych powłoki lub funkcjibash
,csh
(nietcsh
),dash
lubBourne
skryptów powłoki, czyli powłoki, które nie mająwhence -p
(jakksh
lubzsh
) ,command -ev
(jakyash
),whatis -p
(rc
,akanga
) lub wbudowanywhich
(jaktcsh
lubzsh
) w systemach, w którychwhich
jest dostępny i nie jestcsh
skryptem.Jeśli te warunki są spełnione, to:
dałby ci ścieżkę pierwszego
echo
w$PATH
(z wyjątkiem przypadków narożnych), niezależnie od tego, czyecho
zdarza się, że jest to wbudowana powłoka / alias / funkcja czy nie.W innych powłokach wolisz:
echo==echo
lubecho=$commands[echo]
lubecho=${${:-echo}:c}
echo=$(whence -p echo)
echo=$(command -ev echo)
echo=`whatis -p echo`
(uważaj na ścieżki ze spacjami)set echo (type -fp echo)
Zauważ, że jeśli wszystko, co chcesz zrobić, to uruchomić to
echo
polecenie, nie musisz uzyskać jego ścieżki, możesz po prostu zrobić:Na przykład,
tcsh
aby uniemożliwićwhich
użycie wbudowanego :kiedy potrzebujesz zewnętrznego polecenia
Innym przypadkiem, w którym możesz chcieć użyć,
which
jest to, kiedy faktycznie potrzebujesz zewnętrznego polecenia. POSIX wymaga, aby wszystkie wbudowane powłoki (podobnie jakcommand
) były również dostępne jako polecenia zewnętrzne, ale niestety tak nie jestcommand
w wielu systemach. Na przykład rzadko zdarza się znaleźćcommand
polecenie w systemach operacyjnych opartych na systemie Linux, podczas gdy większość z nich mawhich
polecenie (choć różne z różnymi opcjami i zachowaniami).Przypadki, w których możesz chcieć użyć zewnętrznego polecenia, znajdowałyby się wszędzie tam, gdzie wykonywałbyś polecenie bez wywoływania powłoki POSIX.
system("some command line")
,popen()
... Funkcje C lub różnych językach nie wywołuje powłokę do analizowania tego wiersza polecenia, więcsystem("command -v my-cmd")
wykonywać pracę w nich. Wyjątkiem byłby ten,perl
który optymalizuje powłokę, jeśli nie widzi żadnego specjalnego znaku powłoki (innego niż spacja). Dotyczy to również jego operatora zwrotnego:Dodanie tego
:;
powyżej zmuszaperl
do wywołania tam skorupy. Korzystając z tej opcjiwhich
, nie musisz używać tej sztuczki.źródło
which
jestcsh
skryptem na wiele komercyjnych Unices. Powód jest historyczny, dlatego podałem historię, więc ludzie rozumieją, skąd się wziął, dlaczego ludzie przyzwyczaili się do korzystania z niej i dlaczego właściwie nie ma powodu, abyś z niej korzystał. I tak, niektórzy ludzie używają (t) csh. Nie wszyscy jeszcze używają Linuksawhich
, w przeciwieństwie do rzeczy, które możesz próbowaćwhich
zrobić, historiiwhich
, implementacjiwhich
, innych poleceń do wykonania powiązanych zadań lub powodów, dla których faktycznie chcesz użyćwhich
? Dlaczego inne polecenia są lepsze ? Co robią inaczejwhich
? Jak unikają pułapek? Ta odpowiedź faktycznie wydaje więcej słów na problemy z alternatywami niż na problemywhich
.command -v
nie sprawdza uprawnień do wykonywania, przynajmniej jeśli wywołujesz je za pomocą argumentu czystej nazwy pliku bez ścieżki. Testowałem przez dash 0.5.8 i GNU bash 4.3.48.touch /usr/bin/mytestfile
a następnie uruchomięcommand -v mytestfile
go, poda ścieżkę (awhich mytestfile
nie robi).bash
ustali plik wykonywalny, jeśli nie będzie w stanie znaleźć pliku wykonywalnego, więc jest „OK” (chociaż w praktyce wolałbycommand -v
/type
zwrócił błąd), ponieważ jest to polecenie, które próbowałby wykonać podczas uruchamianiamytestfile
, aledash
zachowanie jest błędne, tak jakbycmd
przed plikiem wykonywalnym było coś niewykonywalnego ,command -v
zwraca ono niewykonywalne, podczas gdy wykonywaniecmd
wykonałoby to (także niewłaściwe). FreeBSDsh
(również oparty naash
) ma ten sam błąd. Zsh, yash, ksh, mksh, bash jak sh są OK.Powody, dla których można nie chcieć używać,
which
zostały już wyjaśnione, ale oto kilka przykładów na kilku systemach, w którychwhich
faktycznie zawodzi.W przypadku powłok podobnych do Bourne'a porównujemy dane wyjściowe
which
z danymi wyjściowymitype
(type
jako wbudowana powłoka, ma to być podstawowa prawda, ponieważ jest to powłoka, która mówi nam, jak wywoła polecenie).Wiele przypadków to przypadki narożne , ale należy pamiętać, że
which
/type
są często używane w przypadkach narożnych (aby znaleźć odpowiedź na nieoczekiwane zachowanie, takie jak: dlaczego, u licha, to polecenie zachowuje się tak, do którego ja wzywam? ).Większość systemów, większość powłok Bourne'a: funkcje
Najbardziej oczywistym przypadkiem są funkcje:
Powodem jest to, że
which
raportuje tylko o plikach wykonywalnych, a czasami o aliasach (choć nie zawsze tych w twojej powłoce), a nie funkcjach.GNU, którego strona man ma zepsuty (jak zapomnieli zacytować
$@
) przykład, jak go używać do raportowania funkcji, ale podobnie jak w przypadku aliasów, ponieważ nie implementuje on parsera składni powłoki, łatwo go oszukać:Większość systemów, większość powłok typu Bourne'a: wbudowane
Inna sprawa jest oczywista builtins lub słowa kluczowe, jak
which
jest jakaś komenda nie ma sposobu, aby wiedzieć, które builtins twoja powłoka posiada (i niektóre muszle jakzsh
,bash
lubksh
może załadować poleceń wbudowanych dynamicznie):(nie dotyczy tego,
zsh
gdziewhich
jest wbudowany)Solaris 10, AIX 7.1, HP / UX 11i, Tru64 5.1 i wiele innych:
Jest tak, ponieważ w większości komercyjnych Uniksów
which
(podobnie jak w oryginalnej implementacji na 3BSD) jestcsh
skrypt, który czyta~/.cshrc
. Aliasy, które zgłosi, są zdefiniowane tam niezależnie od aktualnie zdefiniowanych aliasów i niezależnie od używanej powłoki.W HP / UX lub Tru64:
(wersje Solaris i AIX rozwiązały ten problem, zapisując
$path
przed odczytaniem~/.cshrc
i przywracając go przed wyszukaniem poleceń)Lub:
(oczywiście jako
csh
skrypt nie można oczekiwać, że będzie działał z argumentami zawierającymi spacje ...)CentOS 6.4, bash
W tym systemie istnieje zdefiniowany alias dla całego systemu, który otacza
which
polecenie GNU .Wyjście podrobiony dlatego
which
czyta wyjściebash
„salias
, ale nie wie, jak go analizować i prawidłowo używa heurystyki (jeden alias każdym wierszu, wygląda na pierwszy znaleziono polecenia po|
,;
,&
...)Najgorsze w CentOS jest to, że
zsh
ma doskonalewhich
wbudowane polecenie, ale CentOS zdołał go złamać, zastępując go niedziałającym aliasem dla GNUwhich
.Debian 7.0, ksh93:
(chociaż dotyczy większości systemów z wieloma powłokami)
Na Debianie
/bin/which
jest/bin/sh
skryptem. W moim przypadkush
byciedash
jest takie samo, kiedy jestbash
.Unset
PATH
nie ma na celu wyłączeniaPATH
wyszukiwania, ale oznacza użycie domyślnej ścieżki systemu, która niestety w Debianie nikt się nie zgadza (dash
ibash
ma/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
,zsh
ma/bin:/usr/bin:/usr/ucb:/usr/local/bin
,ksh93
ma/bin:/usr/bin
,mksh
ma/usr/bin:/bin
($(getconf PATH)
),execvp()
(jak wenv
) ma:/bin:/usr/bin
(tak, najpierw szuka w bieżącym katalogu! )).Dlatego
which
dostaje to źle powyżej ponieważ używadash
„s domyślnegoPATH
, który jest różny odksh93
” sNie jest lepiej z GNU,
which
który raportuje:(co ciekawe,
/usr/local/bin/which
w moim systemie jest rzeczywiścieakanga
skrypt, który w rzeczywistości został dostarczony ze skryptemakanga
(rc
pochodna powłoki, gdzie domyślniePATH
jest/usr/ucb:/usr/bin:/bin:.
))bash, dowolny system:
Ten, do którego odnosi się Chris w swojej odpowiedzi :
Również po
hash
ręcznym wywołaniu :Teraz przypadek, w którym
which
czasami siętype
nie udaje:Teraz z kilkoma pociskami:
Z innymi:
Ani
which
nietype
może wiedzieć z góry, żeb/foo
nie można go wykonać. Niektóre muszle jakbash
,ksh
lubyash
, gdy powołując sięfoo
rzeczywiście spróbować uruchomićb/foo
i zgłosić błąd, podczas gdy inni (jakzsh
,ash
,csh
,Bourne
,tcsh
) będzie działaća/foo
na niepowodzeniaexecve()
wywołania systemowego sprawieb/foo
.źródło
mksh
faktycznie używa czegoś innego jako domyślnego$PATH
: po pierwsze,_PATH_DEFPATH
używana jest stała czasowa kompilacji systemu operacyjnego (najczęściej na BSD), następnieconfstr(_CS_PATH, …)
używana jest (POSIX), a jeśli obie nie istnieją lub ulegają awarii/bin:/usr/bin:/sbin:/usr/sbin
.ls
jest to funkcja, której używals
z PATH. Iwhich
dobrze jest powiedzieć, który jest używany/usr/bin/ls
lub/usr/local/bin/ls
. Nie widzę „Dlaczego nie skorzystać z którego” ....which ls
da mi/bin/ls
niezależnie od tego, czyls
funkcja zwraca/bin/ls
lub/opt/gnu/bin/ls
lubdir
lub w ogóle nic. IOWwhich
(to, które implementacje, IMMV) daje coś nieistotnegols
jest funkcją. Ja wiem , że mojals
funkcja dzwonils
zPATH
. Terazwhich
mówi mi, gdzie jest plik. Widoczny jest tylko jeden przypadek użycia: „Co moja powłoka zrobiłaby z tym poleceniem”. W tym przypadku użyciewhich
jest nieprawidłowe, popraw. Są jednak inne przypadki użycia, w których (GNU)which
jest dokładnie właściwą rzeczą.which
implementacji. Niektórzy powiedzą, że to jest alias (jeśli masz skonfigurowany alias lub jeśli~/.cshrc
w domu jest taki alias), inni podadzą ci ścieżkę, ale pod pewnymi warunkami niewłaściwy.sh -c 'command -v ls'
, chociaż nie doskonały, jest jeszcze bardziej prawdopodobne, że da ci właściwą odpowiedź na te różne wymagania (i jest również standardem).Jedną rzeczą, która (z mojego szybkiego przeglądu) wydaje się, że Stephane nie wspomniał, jest to, że
which
nie ma pojęcia o tabeli skrótów ścieżki twojej powłoki. Powoduje to, że może zwrócić wynik, który nie jest reprezentatywny dla tego, co jest faktycznie uruchamiane, co czyni go nieefektywnym w debugowaniu.źródło
W duchu UNIX: Niech każdy program robi jedną rzecz dobrze.
Jeśli celem jest odpowiedź: który plik wykonywalny istnieje o tej nazwie?
Dobrym rozwiązaniem jest program wykonywalny dostarczany z systemami Debian. Dostarczone z csh zawierały aliasy, które są źródłem problemów. To, co niektóre powłoki zapewniają jako wbudowane funkcje wewnętrzne, ma inny cel. Użyj tego pliku wykonywalnego lub użyj skryptu podanego na końcu tej odpowiedzi.
Jeśli ten skrypt jest używany, to, co odpowiada, jest czysty, prosty i użyteczny.
Ten cel będzie pasował do pierwszego zdania Twojego pytania:
Jeśli masz system, który nie posiada plik wykonywalny o nazwie, która (większość systemów Linux masz) można utworzyć w
~/bin/which
przed/bin/
w PATH tak osobiste wykonywalne te systemowe przesłanianie jak ten na dole tego postu:Ten plik wykonywalny wyświetli (domyślnie) wszystkie pliki wykonywalne znalezione w ŚCIEŻCE. Jeśli wymagana jest tylko pierwsza, opcja
-f
jest dostępna.W tym momencie osiągamy inny cel:
co powłoka wykona (po parsowaniu)
Pochodzi z Twojego drugiego zdania:
Ten drugi przedmiot próbuje znaleźć dobrą odpowiedź na pytanie, na które trudno jest odpowiedzieć. Muszle mają różne poglądy, przypadki narożne i (co najmniej) różne interpretacje. Dodając do tego:
Oczywiście wszystkie próby odpowiadają temu celowi.
Unikaj który?
Zastanawiam się: dlaczego miałoby to być powiedziane, jeśli
which
działa dobrze (przynajmniej w Debianie)?W duchu UNIX: Niech każdy program robi jedną rzecz dobrze.
Zewnętrzny program,
which
robi jedno: Znajdź pierwszy wykonywalnego na ścieżkę, która ma taką samą nazwę jak nazwa polecenia . I robi to dość dobrze.Nie znam żadnego innego programu ani narzędzia, które odpowiedziałoby na to pytanie w bardziej fundamentalny sposób. Jako taki jest przydatny i może być używany w razie potrzeby.
Najbliższa alternatywa wydaje się być
command -pv commandName
:, ale będzie to również raportować o wbudowanych i aliasach. Nie ta sama odpowiedź.Oczywiście
which
jest ograniczony, nie odpowiada na wszystkie pytania, żadne narzędzie nie mogłoby tego zrobić (cóż, jeszcze nie ...). Ale przydaje się, gdy jest używany do odpowiedzi na pytanie, na które ma odpowiedzieć (to pytanie powyżej). Podobnie jaked
zostało ograniczone, a następniesed
pojawił się (lubvi
/vim
). Lub podobnyawk
był ograniczony i sprawił, że Perl pojawił się i rozszerzył. Jednaked
,sed
i / lubawk
mają szczególne przypadki użycia, gdzievim
alboperl
są nie najlepsze narzędzia.Prawdopodobnie dlatego, że
which
odpowiada tylko na część pytania, które użytkownik powłoki może zadać:Co jest wykonywane, gdy wpisuję polecenie?
Zewnętrzne które
Który powinien być dostępny (w wielu systemach) jako zewnętrzny plik wykonywalny.
Jedynym pewnym sposobem na wywołanie tego narzędzia zewnętrznego jest użycie env, aby wyjść z powłoki, a następnie wywołać
which
(co działa we wszystkich powłokach):Lub użyj pełnej ścieżki do
which
(która może być różna w różnych systemach):Dlaczego to jest
hack
potrzebne? Ponieważ niektóre powłoki (szczególnie zsh) chowają sięwhich
:Będąc narzędziem zewnętrznym (jak
env
) doskonale wyjaśnia, dlaczego nie zgłasza wewnętrznych informacji powłoki. Podobnie jak aliasy, funkcje, wbudowane, specjalne wbudowane, zmienne powłoki (nieeksportowane) itp .:Puste wyjście
ll
(wspólny alias dlall='ls -l'
) wskazuje, żell
nie jest związane z programem wykonywalnym, a przynajmniej, że nie ma pliku wykonywalnego o nazwiell
PATH. Zastosowaniell
powinno wywołać coś innego, w tym przypadku alias:type
icommand
Polecenia
type
icommand -v
są wymagane przez POSIX. Należy się spodziewać, że będą działać w większości muszli i robią to, z wyjątkiem csh, tcsh, fish i rc.Oba polecenia mogą być wykorzystane do zapewnienia innego punktu widzenia, które polecenie zostanie wykonane.
whence
,where
,whereis
,whatis
,hash
Wtedy istnieje
whence
,where
,whereis
,whatis
,hash
, i kilka innych. Wszystkie różne odpowiedzi na podobne pytania. Wszystkie działają na różne sposoby w różnych powłokach. Prawdopodobniewhence
jest najczęstszy potype
. Inne są specjalnymi rozwiązaniami, które odpowiadają na to samo pytanie na różne sposoby.Prawdopodobnie
which
najpierw wiedzieć, czy istnieje plik wykonywalny o nazwie nazwa_polecenia , a następnietype
icommand
, a następnie, jeśli nazwa_polecenia nie zostały jeszcze znalezione:whence
,where
,whereis
,whatis
,hash
w tej kolejności.Skrypt powłoki zapewniający
which
plik wykonywalny.źródło
Nigdy tego nie słyszałem. Podaj konkretne przykłady. Martwiłbym się o twoją dystrybucję linuksa i zainstalowane pakiety oprogramowania, ponieważ to skąd
which
pochodzi!SLES 11,4 x86-64
w wersji tcsh 6.18.01:
w wersji bash 3.2-147:
which
jest częścią util-linux, standardowego pakietu dystrybuowanego przez Linux Kernel Organization do użytku jako część systemu operacyjnego Linux. Zapewnia również te inne plikimoja
util-linux
jest wersja 2.19. Informacje o wersji można łatwo znaleźć w wersji 2.13 z dnia 28 sierpnia 2007 r. Nie jestem pewien, jaki był tego cel lub cel, z pewnością nie udzielono odpowiedzi w tej długiej sprawie, która została poddana głosowaniu 331 razy.źródło
which -v
pokazuje program, jest to GNU (ekstrawaganckie, wspomniane w drugiej odpowiedzi i nie jest w żaden sposób specyficzne dla Linuksa), a nie util-linux, którego AFAIK nigdy nie zawierałwhich
. util-linux 2.19 pochodzi z 2011 roku, GNU, który 2.19 pochodzi z 2008 roku.