Se scrivo
::
in una shell bash, ottengo:
-bash: ::: command not found
Ma solo uno si :
traduce in nessun output. Perchè è questo?
Se scrivo
::
in una shell bash, ottengo:
-bash: ::: command not found
Ma solo uno si :
traduce in nessun output. Perchè è questo?
Risposte:
:
shell integrata vs inesistente::
Il :
guscio di comando integrato esiste (notare la differenza fra esterna e comandi incorporati ), che non fa nulla; restituisce solo successo, proprio come il true
comando. Il :
built-in è standard e definito dallo standard POSIX , dove è anche noto come "null utility". Viene spesso utilizzato per i test o per l'esecuzione di loop infiniti come inwhile : ; do ...;done
bash-4.3$ type :
: is a shell builtin
Tuttavia, ::
- due caratteri di due punti insieme - vengono interpretati come una "parola" nella shell e presuppone che sia un comando immesso dall'utente. La shell passerà attraverso il processo di controllo degli built-in, quindi qualsiasi directory nella PATH
variabile per l'esistenza di quel comando. Ma non esiste un ::
comando incorporato né esterno ::
. Pertanto, ciò produce un errore.
Bene, qual è un formato tipico per un errore?
<shell>: <command user typed>: error message
Pertanto, ciò che vedi non sono 3 punti, ma ciò che hai digitato incollato nel formato di errore standard.
Nota anche che :
può accettare argomenti da riga di comando, vale a dire che è legale fare:
: :
In questo caso, la shell lo considererà come due "parole", una delle quali è un comando e l'altra un parametro posizionale. Anche questo non produrrà alcun errore! (Vedi anche la nota storica (più avanti in questa risposta) sull'uso di of :
con parametri posizionali.)
Si noti che la formattazione può variare anche tra shell diverse. Per bash
, ksh
e mksh
il comportamento è coerente. Ad esempio, la /bin/sh
shell predefinita di Ubuntu (che in realtà è /bin/dash
):
$ dash
$ ::
dash: 1: ::: not found
dove 1 è il numero del comando (equivalente al numero di riga in uno script).
csh
al contrario non produce alcun messaggio di errore:
$ csh
% ::
%
In effetti, se si esegue strace -o csh.trace csh -c ::
, l'output di traccia nel csh.trace
file rivela che csh
esce con lo stato di uscita 0 (nessun errore). Ma tcsh
genera l'errore (senza emetterne il nome, però):
$ tcsh
localhost:~> ::
::: Command not found.
In generale, il primo elemento nel messaggio di errore dovrebbe essere il processo o la funzione di esecuzione (la shell tenta di eseguire ::
, quindi il messaggio di errore proviene dalla shell). Ad esempio, qui il processo di esecuzione è stat
:
$ stat noexist
stat: cannot stat 'noexist': No such file or directory
Infatti, POSIX definisce la funzione perror () , che secondo la documentazione accetta un argomento stringa, quindi genera un messaggio di errore dopo i due punti e quindi newline. Citazione:
La funzione perror () deve mappare il numero di errore a cui si accede tramite il simbolo errno su un messaggio di errore dipendente dalla lingua, che deve essere scritto nel flusso di errore standard come segue:
Innanzitutto (se s non è un puntatore nullo e il carattere indicato da s non è il byte null), la stringa a cui fa riferimento s è seguita da due punti e da uno <spazio>.
Quindi una stringa di messaggio di errore seguita da una <nuova>.
E l'argomento stringa a perror()
tecnicamente potrebbe essere qualsiasi cosa, ma ovviamente per chiarezza è in genere il nome della funzione o argv[0]
.
Al contrario, GNU ha il proprio set di funzioni e variabili per la gestione degli errori , che un programmatore può usare fprintf()
per lo stderr
streaming. Come mostra uno degli esempi nella pagina collegata, si potrebbe fare qualcosa del genere:
fprintf (stderr, "%s: Couldn't open file %s; %s\n",
program_invocation_short_name, name, strerror (errno));
Nella vecchia shell Unix e Thompson, :
veniva usato con la goto
dichiarazione (che secondo l'utente chiamato Perderabo su questo thread non era una shell integrata). Citazione dal manuale:
L'intero file di comando viene cercato per una riga che inizia con un: come primo carattere non vuoto, seguito da uno o più spazi vuoti, quindi dall'etichetta. Se viene trovata una tale linea, goto riposiziona l'offset del file di comando sulla riga dopo l'etichetta ed esce. Questo fa sì che la shell si trasferisca sulla linea etichettata.
Quindi potresti fare qualcosa del genere per creare uno script loop infinito:
: repeat
echo "Hello World"
goto repeat
command.com
e Windows ' cmd.exe
hanno una situazione simile ma opposta: :
è esplicitamente un'etichetta goto (non un comando) e spesso riproposta come carattere di commento (ad es :: This is a comment
.).
Gli ultimi due punti sono solo una parte del messaggio predefinito "non trovato":
$ x
x: command not found
$ ::
::: command not found
La ragione per cui un singolo colon non produce nulla è che :
è un comando valido, sebbene non faccia nulla (tranne il ritorno TRUE
). Dalla SHELL BUILTIN COMMANDS
sezione di man bash
:
: [arguments]
No effect; the command does nothing beyond expanding arguments
and performing any specified redirections. A zero exit code is
returned.
A volte lo vedrai in costruzioni come
while :
do
something
done
Vedi per esempio A che cosa serve il colon incorporato?
I due punti aggiunti fanno parte del messaggio di errore stesso. Se si digita, cd ow
ne risulta uno bash: cd: ow: No such file or directory
, il che dimostra che l'errore sta mettendo i due punti in più: No such file or directory
$ ::
bash: ::: command not found
$ kkkk
bash: kkkk: command not found
il terzo è un distanziatore dalla formattazione
in bash a :
è un'istruzione vuota vuota