echo scrive a schermo il testo che gli passi, seguito da un a capo. È il comando più semplice del terminale e uno dei più usati: serve a mostrare messaggi, a leggere il valore di una variabile, a scrivere una riga in un file e a fare prove prima di eseguire comandi pericolosi.
Cos'è
echo significa "eco": ripete ciò che riceve. Esiste in due versioni: come comando interno (builtin) della shell, che è quella usata normalmente, e come eseguibile separato, /usr/bin/echo, del pacchetto GNU coreutils. Come visto per pwd, puoi verificarlo con:
$ type -a echo
echo is a shell builtin
echo is /usr/bin/echoLe due versioni si comportano in modo quasi identico, ma non del tutto: le differenze di dettaglio sono la ragione per cui negli script più delicati si preferisce printf (ne parliamo in fondo).
Cosa fa
Prende i suoi argomenti, li separa con uno spazio e li stampa sullo standard output, aggiungendo un carattere di a capo finale. Non legge file e non modifica nulla, a meno che tu non reindirizzi il suo output. Una cosa da tenere sempre a mente: il lavoro di interpretare variabili, caratteri jolly e virgolette lo fa la shell prima ancora che echo parta. A echo arriva già il testo risolto.
Come si usa
$ echo [opzioni] [testo...]Esempio 1: stampare un messaggio
$ echo Ciao, mondo
Ciao, mondo
$ echo "Ciao, mondo"
Ciao, mondoLe virgolette non fanno parte del testo: servono alla shell. Per i messaggi con punteggiatura o spazi conviene sempre metterle.
Esempio 2: le virgolette contano
$ echo uno due tre
uno due tre
$ echo "uno due tre"
uno due treSenza virgolette la shell spezza il testo in parole e butta via gli spazi in eccesso: echo riceve tre argomenti e li rimette insieme con uno spazio solo. Con le virgolette riceve un unico argomento e lo stampa com'è.
Esempio 3: leggere una variabile
$ echo "$HOME"
/home/enzo
$ echo "Utente: $USER, shell: $SHELL"
Utente: enzo, shell: /bin/bash
$ echo "$PATH"
/usr/local/bin:/usr/bin:/binIl segno $ davanti a un nome dice alla shell di sostituirlo con il valore della variabile. echo è il modo più rapido per controllare cosa contiene una variabile d'ambiente.
Esempio 4: apici singoli e doppi
$ echo "Casa: $HOME"
Casa: /home/enzo
$ echo 'Casa: $HOME'
Casa: $HOMELe virgolette doppie lasciano agire la shell sulle variabili; gli apici singoli la bloccano del tutto e il testo resta letterale. Se nel testo c'è un apostrofo, usa le virgolette doppie: echo "L'altra casa".
Esempio 5: inserire il risultato di un comando
$ echo "Oggi è $(date +%A)"
Oggi è mercoledì
$ echo "Sono in: $(pwd)"
Sono in: /home/enzo
$ echo "File in questa cartella: $(ls | wc -l)"
File in questa cartella: 12La forma $(comando) viene sostituita dall'output del comando.
Esempio 6: il codice di uscita con $?
$ ls /cartella_inesistente
ls: impossibile accedere a '/cartella_inesistente': File o directory non esistente
$ echo $?
2
$ ls /etc > /dev/null
$ echo $?
0La variabile speciale $? contiene il codice di uscita dell'ultimo comando: 0 significa successo, qualsiasi altro numero un errore. È uno degli usi più frequenti di echo quando si prova uno script. Altre variabili utili da guardare con echo: $$ (il PID della shell), $0 (il nome della shell o dello script), $# (quanti argomenti ha ricevuto uno script).
Esempio 7: senza a capo con -n
$ echo -n "Continuo..."
Continuo...$
$ echo "ciao" | wc -c
5
$ echo -n "ciao" | wc -c
4Con -n echo non aggiunge l'a capo finale (nel primo esempio il prompt rimane attaccato al testo). La differenza conta quando si conta o si elabora il testo, come mostra wc -c: "ciao" ha 4 caratteri, ma echo normalmente ne aggiunge uno, l'a capo.
Esempio 8: sequenze speciali con -e
$ echo -e "riga 1\nriga 2"
riga 1
riga 2
$ echo -e "nome\tcognome"
nome cognomeCon -e echo interpreta le sequenze introdotte dalla barra rovesciata. Le principali:
| Sequenza | Significato |
|---|---|
\n | A capo |
\t | Tabulazione |
\\ | Una barra rovesciata |
\a | Segnale acustico (il "beep" del terminale) |
\e o \033 | Carattere di escape, per i colori del terminale |
Senza -e il testo resta com'è: echo "a\nb" stampa proprio a\nb. In Bash esiste anche un'alternativa, la citazione $'...', che interpreta le sequenze senza bisogno di -e:
$ echo $'riga 1\nriga 2'Esempio 9: messaggi colorati
$ echo -e "\e[31mErrore\e[0m: file non trovato"
$ echo -e "\e[32mFatto\e[0m"Le sequenze \e[...m cambiano il colore del testo nel terminale: 31 rosso, 32 verde, 33 giallo, 34 blu, 0 ripristina i colori normali. Dimenticare il \e[0m finale lascia il terminale colorato fino al comando successivo.
Esempio 10: scrivere in un file
$ echo "prima riga" > note.txt
$ echo "seconda riga" >> note.txt
$ cat note.txt
prima riga
seconda rigaCon > l'output di echo finisce in un file, che viene creato o svuotato; con >> viene aggiunto in coda. È il modo più veloce per creare un file con una riga di contenuto, a differenza di touch, che lo crea vuoto.
Esempio 11: vedere cosa farebbe la shell
$ ls
appunti.txt cache.tmp lista.txt vecchio.tmp
$ echo *
appunti.txt cache.tmp lista.txt vecchio.tmp
$ echo *.tmp
cache.tmp vecchio.tmp
$ echo rm *.tmp
rm cache.tmp vecchio.tmpI caratteri jolly li espande la shell, non echo: scrivere echo *.tmp mostra l'elenco esatto dei file che il carattere jolly selezionerebbe. L'ultimo comando, con echo davanti, è un'anteprima: mostra il comando che verrebbe eseguito, senza eseguirlo. È un'ottima abitudine prima di un rm con caratteri jolly.
Esempio 12: espansioni con le parentesi graffe
$ echo {1..5}
1 2 3 4 5
$ echo file{1..3}.txt
file1.txt file2.txt file3.txt
$ echo {a,b,c}
a b c
$ echo ~
/home/enzoAnche queste espansioni sono compito della shell, e echo è un modo comodo per provarle prima di usarle con mkdir o touch.
Esempio 13: in coda ad altri comandi
$ echo "3 1 2" | tr ' ' '\n' | sort
1
2
3
$ echo "ciao mondo" | tr a-z A-Z
CIAO MONDO
$ echo "testo di prova" | sed 's/prova/esempio/'
testo di esempioCon la pipe | si dà a un altro comando un testo da elaborare, senza creare un file. Il comando tr sostituisce o elimina caratteri; sed lo conosci già.
Esempio 14: messaggi di errore e di debug
$ echo "Errore: file non trovato" >&2Con >&2 il messaggio va sul canale degli errori (stderr) invece che sull'output normale. Negli script è la convenzione per i messaggi di errore e di debug, perché non si mescolano con i risultati che qualcuno potrebbe reindirizzare o passare a un altro comando.
Esempio 15: uso negli script
#!/bin/bash
NOME="${1:-mondo}"
echo "Ciao, $NOME!"
echo "Oggi è $(date +%A)"
echo "Sono in: $(pwd)"
echo "Argomenti ricevuti: $#"
if [ ! -d "$HOME/backup" ]; then
echo "Cartella backup assente" >&2
exit 1
fi
VERDE='\e[32m'
RESET='\e[0m'
echo -e "${VERDE}Tutto a posto${RESET}"La costruzione ${1:-mondo} prende il primo argomento dello script e, se manca, usa "mondo". Lanciato come ./saluto.sh Enzo, stampa "Ciao, Enzo!".
Esempio 16: la versione portabile, printf
$ printf "%s\n" "Ciao, mondo"
Ciao, mondo
$ printf "%s ha %d anni\n" Mario 42
Mario ha 42 anni
$ printf "%-10s|%5d|\n" mele 12
mele | 12|Il comando printf funziona come in linguaggio C: si scrive un modello con dei segnaposto (%s per il testo, %d per i numeri interi) e poi i valori. Non aggiunge l'a capo se non lo scrivi (\n) e si comporta in modo uguale in tutte le shell. Con %-10s il testo viene allineato a sinistra su 10 caratteri, con %5d il numero a destra su 5: utile per le tabelle.
Opzioni utili
-n: non aggiunge l'a capo finale.-e: interpreta le sequenze con la barra rovesciata (\n,\t,\e...).-E: non le interpreta (è il comportamento predefinito in Bash).--helpe--version: sono riconosciute solo dall'eseguibile/usr/bin/echo, non dal comando interno di Bash (per quello c'èhelp echo).
Attenzione a
- Le variabili senza virgolette:
echo $VARè rischioso se il valore contiene spazi o caratteri jolly. Esempio: conVAR="*",echo $VARstampa l'elenco dei file della cartella corrente, e non l'asterisco. Scrivi sempreecho "$VAR". - Il punto esclamativo: in una shell interattiva,
echo "Ciao!"può darebash: !": event not found, perché Bash interpreta!come richiamo della cronologia, anche tra virgolette doppie. Usa gli apici singoli (echo 'Ciao!') oppure disattiva la funzione conset +H. Negli script il problema non c'è. >sovrascrive:echo "x" > filesvuota il file prima di scriverci. Per aggiungere usa>>.- Con
sudo:sudo echo "riga" >> /etc/hostsnon funziona, perché il reindirizzamento lo esegue la tua shell senza privilegi. Usaecho "riga" | sudo tee -a /etc/hosts, come visto nell'articolo susudo. L'a capo finale cambia il risultato: nei calcoli di somme di controllo, nel conteggio dei caratteri o quando si passa un valore a un altro programma,
echo "abc"inviaabcpiù l'a capo. Un esempio classico:$ echo "abc" | sha256sum edeaaff3f1774ad2... - $ echo -n "abc" | sha256sum ba7816bf8f01cfea... -Sono due somme di controllo diverse, perché il testo è diverso. Se ti serve il testo esatto, usa
echo -noprintf.- Portabilità di
-ee-n: non tutte le shell si comportano come Bash. Nella shellshdi Debian e Ubuntu (dash) l'echointerno interpreta già le sequenze con la barra rovesciata e non riconosce-e, che stamperebbe come testo. Se lo script ha come prima riga#!/bin/sh, usaprintf; con#!/bin/bashpuoi usareecho -e. - Testo che comincia con un trattino: se la variabile contiene qualcosa come
-no-e,echo "$VAR"lo prende per un'opzione e non lo stampa. Per stampare in modo sicuro un valore qualsiasi usaprintf '%s\n' "$VAR". - Mai le password sulla riga di comando:
echo "miapassword" | programmalascia la password nella cronologia dei comandi (history). Passarla come argomento di un programma la rende visibile anche a chiunque guardi l'elenco dei processi conps. Per le password, i programmi hanno di solito un'opzione per leggerle da file o da un input riservato. echoriesce quasi sempre: il suo codice di uscita è 0 anche se stampa un messaggio di errore. Non usarlo per capire se un comando è andato a buon fine: guarda$?o il test conif.- Sequenze di colore: i codici
\e[...mdipendono dal terminale. Se l'output viene reindirizzato in un file, i codici vengono scritti nel file come caratteri strani (li vedi concat -A). Negli script conviene colorare solo se l'output va a un terminale.
Riepilogo
| Comando | Cosa fa |
|---|---|
echo "testo" | Stampa il testo con un a capo |
echo "$VAR" | Mostra il valore di una variabile |
echo 'testo $VAR' | Stampa il testo letterale, senza espansioni |
echo "Oggi: $(date +%F)" | Inserisce l'output di un comando |
echo $? | Codice di uscita dell'ultimo comando |
echo -n "testo" | Stampa senza a capo finale |
echo -e "a\nb" | Interpreta le sequenze con la barra rovesciata |
echo "x" > file / >> file | Scrive nel file / aggiunge in coda |
echo *.tmp | Mostra cosa selezionerebbe un carattere jolly |
echo rm *.tmp | Anteprima di un comando, senza eseguirlo |
echo "errore" >&2 | Scrive sul canale degli errori |
printf '%s\n' "$VAR" | Alternativa portabile e sicura |