Dlaczego komunikat o błędzie dla dwóch dwukropków jako polecenie (: :) w bash ma trzy dwukropki, ale pojedynczy dwukropek nie daje danych wyjściowych?

27

Jeśli piszę

::

w bash shell otrzymuję:

-bash: ::: command not found

Ale tylko jeden :powoduje brak wyników. Dlaczego to?

NerdOfLinux
źródło
Komentarze nie są przeznaczone do rozszerzonej dyskusji; ta rozmowa została przeniesiona do czatu .
Thomas Ward
Jak to się ma do Ubuntu?
NerdOfCode
@NerdOfCode w ten sam sposób? meta.askubuntu.com/q/17076/158442
mur

Odpowiedzi:

40

:Shell wbudowaną vs nieistniejące::

: Powłoka wbudowane polecenie istnieje (zwróć uwagę na różnicę pomiędzy zewnętrznym i wbudowanych komend ), który nic nie robi; po prostu zwraca sukces, tak jak truepolecenie. :Wbudowany jest standardowe i zdefiniowane przez standard POSIX , gdzie jest znany również jako „narzędzia” zerowej. Jest często używany do testowania lub uruchamiania nieskończonych pętli jak wwhile : ; do ...;done

bash-4.3$ type :
: is a shell builtin

Jednak ::- dwa znaki dwukropka razem - są interpretowane jako jedno „słowo” dla powłoki i zakłada się, że jest to polecenie wprowadzone przez użytkownika. Powłoka przejdzie proces sprawdzania wbudowanych, a następnie dowolnego katalogu w PATHzmiennej pod kątem istnienia tego polecenia. Ale nie ma wbudowanego :: ani zewnętrznego polecenia ::. Dlatego powoduje to błąd.

Jaki jest typowy format błędu?

<shell>: <command user typed>: error message

Zatem to, co widzisz, nie jest 3 dwukropkami, ale to, co wpisałeś, wkleiło się do standardowego formatu błędu.

Zauważ też, że :mogą przyjmować argumenty wiersza poleceń, tzn. Legalne jest:

: :

W takim przypadku powłoka uzna to za dwa „słowa”, z których jedno jest poleceniem, a drugie parametrem pozycyjnym. To również nie spowoduje błędu! (Zobacz także notę ​​historyczną (w dalszej części tej odpowiedzi) na temat używania :parametru z parametrami pozycyjnymi).


W muszlach innych niż bash

Pamiętaj, że formatowanie może również różnić się w zależności od powłoki. Dla bash, kshi mkshzachowanie jest spójne. Na przykład domyślna /bin/shpowłoka Ubuntu (która jest w rzeczywistości /bin/dash):

$ dash
$ ::
dash: 1: ::: not found

gdzie 1 to numer polecenia (odpowiednik numeru wiersza w skrypcie).

csh dla kontrastu nie generuje żadnego komunikatu o błędzie:

$ csh
% ::
%

W rzeczywistości, jeśli uruchomisz strace -o csh.trace csh -c ::, dane wyjściowe śledzenia w csh.tracepliku ujawnią, że cshkończy się ze statusem wyjścia 0 (bez błędów). Ale tcshgeneruje błąd (jednak bez wypisywania swojej nazwy):

$ tcsh
localhost:~> ::
::: Command not found.

Komunikaty o błędach

Ogólnie rzecz biorąc, pierwszym elementem w komunikacie o błędzie powinien być proces lub funkcja wykonująca (powłoka próbuje wykonać ::, dlatego komunikat o błędzie pochodzi z powłoki). Na przykład tutaj proces wykonawczy to stat:

$ stat noexist
stat: cannot stat 'noexist': No such file or directory

W rzeczywistości POSIX definiuje funkcję perror () , która zgodnie z dokumentacją przyjmuje argument łańcuchowy, a następnie wyświetla dwukropek komunikat o błędzie, a następnie znak nowej linii. Zacytować:

Funkcja perror () odwzorowuje numer błędu dostępny poprzez symbol errno na zależny od języka komunikat o błędzie, który należy zapisać w standardowym strumieniu błędów w następujący sposób:

  • Po pierwsze (jeśli s nie jest wskaźnikiem pustym, a znak wskazywany przez s nie jest bajtem pustym), ciąg wskazany przez s, po którym następuje dwukropek i <spacja>.

  • Następnie ciąg komunikatu o błędzie, po którym następuje <nowa linia>.

Argumentem łańcuchowym perror()technicznie może być cokolwiek, ale oczywiście dla jasności jest to zazwyczaj nazwa funkcji lub argv[0].

Z kolei GNU ma swój własny zestaw funkcji i zmiennych do obsługi błędów , z których programista może korzystać fprintf()do stderrstrumieniowania. Jak pokazuje jeden z przykładów na połączonej stronie, można zrobić coś takiego:

  fprintf (stderr, "%s: Couldn't open file %s; %s\n",
           program_invocation_short_name, name, strerror (errno));

Nota historyczna

W starej powłoce Uniksa i Thompsona :użyto gotoinstrukcji (która według użytkownika o nazwie Perderabo w tym wątku nie była wbudowaną powłoką). Cytat z instrukcji:

Cały plik poleceń jest przeszukiwany pod kątem linii rozpoczynającej się od: jako pierwszego niepustego znaku, po którym następuje jeden lub więcej spacji, a następnie etykieta. Jeśli taka linia zostanie znaleziona, goto przesuwa przesunięcie pliku poleceń do linii po etykiecie i kończy działanie. Powoduje to, że powłoka przechodzi do oznaczonej linii.

Możesz więc zrobić coś takiego, aby stworzyć nieskończony skrypt pętli:

: repeat
echo "Hello World"
goto repeat
Sergiy Kolodyazhnyy
źródło
Literówka
1
DOS command.comi Windows ' cmd.exemają podobną, ale odwrotną sytuację: :jest to wyraźnie etykieta goto (a nie polecenie) i często zmienia przeznaczenie jako znak komentarza (np :: This is a comment.).
grawity
54

Ostatni dwukropek jest tylko częścią domyślnego komunikatu „nie znaleziono”:

$ x
x: command not found
$ ::
::: command not found

Powodem, dla którego pojedynczy dwukropek nie produkuje nic, : jest prawidłowe polecenie - chociaż nie robi nic (oprócz powrotu TRUE). Z SHELL BUILTIN COMMANDSsekcji man bash:

   : [arguments]
          No effect; the command does nothing beyond  expanding  arguments
          and  performing any specified redirections.  A zero exit code is
          returned.

Czasami zobaczysz to w konstrukcjach takich jak

while :
do
  something
done

Zobacz na przykład Jaki jest cel wbudowanego dwukropka?

steeldriver
źródło
tak, to jest najbardziej wszechstronny komentarz .. o wiele bardziej wymowny niż mój .. o wiele lepiej wyjaśniony: D
John Orion
8

Wypróbuj dowolne inne nieistniejące polecenie, a zobaczysz, że :służy ono normalnie po angielsku:

$ ---
---: command not found
Olorin
źródło
6

Dodany dwukropek jest częścią samego komunikatu o błędzie. Jeśli jeden wpisze cd ow, spowoduje to bash: cd: ow: No such file or directory, co pokazuje, że błąd polega na wstawieniu dodatkowego dwukropka: No such file or directory

John Orion
źródło
6
$ ::
bash: ::: command not found
$ kkkk
bash: kkkk: command not found

trzeci jest odstępem od formatowania

w bash a :jest pustą instrukcją void

użytkownik688056
źródło
4

otrzymujesz 3 dwukropki, ponieważ format błędu zawiera dwukropek:

bash: <command>: command not found
pustkowie
źródło