È uscito il Corso Java Completo
Torna al blog

Cos'è la shell Bash e come funziona davvero

Cosa fa una shell, perché Bash è ancora lo standard, come funzionano espansioni, pipe e redirezioni, e cosa cambia con Zsh e Fish.

Edoardo Midali

Edoardo Midali

Developer · Content Creator

6 min di lettura

Quando apri un terminale non stai parlando direttamente con Linux: stai parlando con un programma che sta in mezzo, interpreta quello che scrivi e chiede al sistema di eseguirlo. Quel programma è la shell. Capire cosa fa prima di eseguire un comando spiega la maggior parte dei comportamenti che all'inizio sembrano magici o inspiegabili.

Cos'è

La shell è il programma che legge quello che scrivi nel terminale, lo interpreta secondo regole precise e chiede al sistema operativo di eseguire i comandi risultanti.

Distinzione che genera confusione all'inizio: il terminale è la finestra, la shell è il programma che ci gira dentro. Sono cose diverse. Puoi cambiare shell mantenendo lo stesso terminale, e viceversa.

Bash (Bourne Again Shell) è la shell predefinita su gran parte dei server Linux da decenni. Non perché sia la migliore da usare a mano — su quel fronte ha alternative più comode — ma perché è ovunque, e uno script scritto per Bash gira praticamente su qualsiasi macchina Linux tu incontri.

Il punto che cambia tutto: l'espansione

Ecco la cosa che quasi nessuno spiega all'inizio e che spiega metà dei comportamenti strani.

Prima di eseguire qualsiasi cosa, la shell riscrive la riga che hai scritto. Il comando riceve il risultato della riscrittura, non quello che hai digitato.

rm *.txt

rm non vede mai *.txt. La shell espande l'asterisco nell'elenco dei file che corrispondono, e passa a rm quell'elenco già pronto.

Le espansioni principali:

echo *.md              # nomi di file (glob)
echo ~                 # la tua home
echo $HOME             # variabili
echo $(date)           # output di un altro comando
echo {a,b,c}.txt       # a.txt b.txt c.txt

Conseguenza pratica importante: se un nome di file contiene spazi e non lo metti tra virgolette, la shell lo spezza in più argomenti.

rm il mio file.txt      # prova a cancellare TRE file
rm "il mio file.txt"    # corretto

Le virgolette non sono decorazione: dicono alla shell di non spezzare e, nel caso degli apici singoli, di non espandere affatto.

echo "oggi è $USER"    # espande la variabile
echo 'oggi è $USER'    # stampa $USER letterale

Pipe e redirezioni

Qui sta il vero potere della riga di comando, ed è concettualmente semplice.

Ogni programma ha un ingresso e due uscite: input standard, output standard, errori standard. La shell può ricollegarli.

La pipe collega l'uscita di un programma all'ingresso del successivo:

cat log.txt | grep errore | wc -l

Tre programmi semplici che, combinati, contano le righe di errore. Nessuno dei tre sa dell'esistenza degli altri.

Le redirezioni scrivono su file invece che a schermo:

comando > file.txt      # scrive (sovrascrive)
comando >> file.txt     # aggiunge in fondo
comando 2> errori.txt   # solo gli errori
comando > out.txt 2>&1  # tutto insieme
comando < input.txt     # legge da file

> sovrascrive senza chiedere conferma. È uno dei modi più rapidi per perdere un file: se sbagli e scrivi > dove volevi >>, il contenuto precedente sparisce.

Questa capacità di comporre è il motivo per cui i comandi Linux essenziali contano meno individualmente di quanto contino combinati.

Le variabili

nome="Edoardo"
echo "ciao $nome"

Attenzione: niente spazi attorno all'uguale. nome = "x" non è un'assegnazione, e la shell prova a eseguire un programma chiamato nome.

Le variabili d'ambiente sono variabili che i programmi avviati dalla shell possono leggere:

export API_KEY="..."   # visibile ai programmi lanciati
env                     # elenco completo
echo $PATH              # dove la shell cerca i comandi

PATH merita attenzione: è l'elenco di cartelle in cui la shell cerca un comando quando ne scrivi il nome. Il classico "command not found" per un programma che sai di aver installato è quasi sempre una cartella mancante nel PATH.

Concatenare comandi

comando1 ; comando2      # esegui entrambi, sempre
comando1 && comando2     # il secondo solo se il primo riesce
comando1 || comando2     # il secondo solo se il primo fallisce
comando &                # esegui in background

&& è quello che userai di più, ed è una piccola rete di sicurezza: cd cartella && rm -rf * non cancella nulla se la cartella non esiste, mentre con ; cancellerebbe nella cartella corrente. La differenza tra i due caratteri è, in quel caso, la differenza tra un disastro e niente.

Configurazione e comodità

Bash legge dei file all'avvio, dove puoi mettere le tue personalizzazioni:

  • ~/.bashrc — sessioni interattive (il caso normale)
  • ~/.bash_profile / ~/.profile — sessioni di login

Gli alias sono la personalizzazione più utile:

alias ll='ls -lah'
alias gs='git status'

Mettili in ~/.bashrc per averli sempre. Ricarica con source ~/.bashrc.

Scorciatoie che fanno risparmiare più tempo di qualsiasi alias:

TastiCosa fa
TabCompleta nomi e percorsi
Comandi precedenti
Ctrl+RCerca nella cronologia
Ctrl+CInterrompe
Ctrl+A / Ctrl+EInizio / fine riga
Ctrl+LPulisce lo schermo

Ctrl+R è la più sottovalutata: inizi a scrivere un pezzo di un comando usato giorni fa e la shell lo ritrova.

Bash, Zsh o Fish?

BashZshFish
Presente ovunqueSpessoRaramente
Comodità d'usoBaseAltaAltissima
ConfigurazioneManualeManuale o frameworkGià pronta
Compatibile con script BashQuasi sempreNo

Zsh è la predefinita su macOS e aggiunge completamento e correzioni molto migliori restando compatibile. Fish è la più comoda appena installata, ma la sua sintassi è diversa: gli script trovati online non funzionano senza adattamenti.

Il consiglio pratico: usa quello che preferisci a mano, ma scrivi gli script in Bash. Sui server trovi Bash, e uno script che gira solo sulla tua macchina è un problema che si presenta nel momento peggiore.

In sintesi

La shell interpreta quello che scrivi prima di eseguirlo, e questo spiega la maggior parte dei comportamenti che sembrano strani: espansioni, virgolette, nomi con spazi.

Le due idee da portare a casa sono l'espansione — il comando non riceve quello che hai digitato — e la composizione tramite pipe, che rende utili strumenti semplici messi in fila.

Bash resta lo standard sui server: comoda a mano quanto basta, universale dove conta. Per l'uso quotidiano puoi passare a Zsh senza rinunce, ma gli script conviene tenerli compatibili con Bash.

Il passo successivo naturale è automatizzare: quando una sequenza di comandi si ripete, diventa uno script. Se lavori su un server, il contesto completo è in come configurare un VPS da zero; se parti da prima, il quadro d'insieme è in cos'è Linux.