Stworzyłem prosty program C taki jak:
int main(int argc, char *argv[]) {
if (argc != 5) {
fputs("Not enough arguments!\n", stderr);
exit(EXIT_FAILURE);
}
I mam zmienioną PATH w etc / bash.bashrc w następujący sposób:
PATH=.:$PATH
Zapisałem ten program jako set.c i kompiluję go
gcc -o set set.c
w folderze
~/Programming/so
Jednak kiedy dzwonię
set 2 3
nic się nie dzieje. Brak wyświetlanego tekstu.
Powołanie
./set 2 3
daje oczekiwany wynik
Nigdy wcześniej nie miałem problemu z PATH
which set
zwraca ./set
. Wygląda więc na to, że ŚCIEŻKA jest poprawna. Co się dzieje
shell
path
shell-builtin
Ganea Dan Andrei
źródło
źródło
test
z tego samego powodu;test
jest również wbudowany w powłokę.test
wydają się mieć sens. Oczywiście, zanim go włożyszPATH
, naprawdę powinieneś wymyślić inne imię. I dopóki nie włożysz programu do swojego programu,PATH
będziesz musiał go w./test
każdym razie wywołać . Dlatego używanie nazwytest
programu jest w porządku, o ile jest to szybki test, który zamierzasz usunąć przed końcem dnia.foo
.ls
nazwiesz, to za każdym razem, gdy zobaczysz, czy istnieje, uruchomi się (ale tylko jeśli zmienisz ścieżkę, tak jak w pytaniu).Odpowiedzi:
Zamiast używać
which
, która nie działa, gdy jest najbardziej potrzebna , użyj,type
aby określić, co będzie działać po wpisaniu polecenia:Powłoka zawsze szuka wbudowanych przed przeszukaniem
$PATH
, więc ustawienie$PATH
tutaj nie pomaga.Najlepiej byłoby zmienić nazwę pliku wykonywalnego na coś innego, ale jeśli twoje przypisanie wymaga nazwy programu
set
, możesz użyć funkcji powłoki:(To działa
bash
, ale inne podobne powłokiksh
mogą na to nie zezwalać. Zobacz odpowiedź mikeserv na bardziej przenośne rozwiązanie).Teraz podczas wpisywania
set
uruchomiona zostanie funkcja o nazwie „set”, która zostanie wykonana./set
. GNUbash
szuka funkcji przed szukaniem wbudowanych i szuka wbudowanych przed przeszukaniem$PATH
. Sekcja o nazwie „WYKONANIE POLECEŃ” na stronie podręcznika użytkownika bash zawiera więcej informacji na ten temat.Zobacz także dokumentację
builtin
icommand
:help builtin
ihelp command
.źródło
type
ponadwhich
, ale nie podawaj żadnego powodu. ( Wiem dlaczego , ale ktoś, kto potrzebuje rekomendacji, nie zrobiłby tego).type
zamiastwhich
, nie nazywaj swojego programu „set” i zdaj sobie sprawę, żefunction set { ./set; }
to brzydki hack, którego prawdopodobnie powinieneś unikać.set
jest wbudowany w bash (i prawdopodobnie większość innych powłok). Oznacza to, że bash nawet nie przeszuka ścieżki podczas szukania funkcji.Na marginesie stanowczo odradzam dodawanie
.
do ścieżki ze względów bezpieczeństwa. Wyobraź sobie na przykład,cd
że/tmp
po dodaniu pliku wykonywalnego przez innego użytkownika/tmp/cd
.źródło
cd
jest wbudowaną powłoką, więc przykład nie będzie działał z tego samego powodu co zset
../foo
do wywoływania programu jest profesjonalne; pokazuje, że rozumiesz, dlaczego.
nie powinno być w $ PATH. Twój nauczyciel się myli i możesz mu powiedzieć, że tak powiedziałem.set
to nie tylko wbudowane, to specjalne wbudowane POSIX . Istnieje kilka wbudowanych poleceń, które są określone w standardach, które można znaleźć w wyszukiwaniu poleceń, zanim cokolwiek innego -$PATH
nie jest przeszukiwane, nazwy funkcji nie są przeszukiwane itp. Większość wbudowanych, które nie są specjalne, są w rzeczywistości wymagane przez standard POSIX znalezione w tobie,$PATH
zanim powłoka uruchomi dowolną z wbudowanych procedur. To jest prawdaecho
i większość innych (choć czy średnia jest honorowana w tym względzie była kwestią sporną w listach dyskusyjnych Open Group w przeszłości) , ale nie zset
,trap
,break
,return
,continue
,.
,:
,times
,eval
,exit
,export
,readonly
,unset
, Lubexec
.Wszystkie są zastrzeżonymi nazwami powłoki i mają specjalne atrybuty inne niż ich kolejność w wyszukiwaniu poleceń. Na przykład nie można zdefiniować funkcji powłoki o żadnej z tych nazw w powłoce zgodnej ze standardami. To dobra rzecz - pozwala ludziom bezpiecznie pisać przenośne skrypty . Są to podstawowe polecenia, dzięki którym doświadczony pisarz skryptów może ustanowić bezpieczną i niezawodną bazę w swoim środowisku. Zaatakowanie tego obszaru nazw nie jest wskazane.
Jeśli jednak chcesz go zaatakować, możesz to zrobić przenośnie
alias
. Kolejność rozszerzania powłoki umożliwia obejście tego problemu. Ponieważalias
rozszerzenie jest rozwijane podczas odczytywania polecenia, cokolwiek zastąpiset
nazwę w definicji, rozwinie się poprawnie, po prostu prawdopodobnie nie powinno rozwinąć się do jednej z tych nazw.Więc możesz zrobić:
... które będą działać dobrze.
źródło
Problem polega na tym, że
set
jest to wbudowana powłoka, a najlepszym rozwiązaniem byłoby użycie innej nazwy dla programu wykonywalnego.Nawiasem mówiąc, w zeszłym tygodniu zadałem pytanie, jak uruchamiać polecenia systemowe zamiast wbudowanych powłok o tej samej nazwie, a rozwiązaniem, które zaakceptowałem, było uruchomienie polecenia przez
env
:W tym konkretnym przypadku, gdy już wiesz, że polecenie, którego chcesz użyć, znajduje się w twoim bieżącym katalogu, lepiej byłoby bezpośrednio uruchomić plik wykonywalny, wprowadzając jego ścieżkę (używając
.
do reprezentowania bieżącego katalogu roboczego):Oba powyższe rozwiązania są niezależne od powłoki, tzn. Będą działać niezależnie od używanej powłoki.
Sugestie takie jak użycie
command
wbudowanego nie działają w Bash: to tylko zapobiega uruchomieniu funkcji powłoki . Chociaż nie jest to udokumentowane, zauważyłem również, że użyciecommand
również tłumi słowa kluczowe powłoki . Jednak nie zrobi tego samego dla wbudowanych powłok, takich jakset
. Jak rozumiem,command
może współpracować z innymi powłokami, takimi jak zsh.Również sztuczek takich jak
\set
lub"set"
czy'set'
nie pracują za Bash builtins - choć są one przydatne do uruchamiania plików wykonywalnych zamiast aliasów lub skorupą słów kluczowych .Uwaga: Ta odpowiedź początkowo była komentarzem do (zaakceptowanej) odpowiedzi Erica, ale stała się zbyt duża, aby zmieścić się w komentarzu. Inne odpowiedzi zalecające użycie ŚCIEŻKI
type
i nie dodawanie jej.
do PATH są dobre.źródło