Hai scritto un comando lungo due giorni fa e non ricordi come? Hai digitato cat /etc/shadow e ti sei accorto di aver dimenticato sudo? Il terminale si ricorda tutto quello che scrivi, e history serve a ritrovarlo, a ripeterlo e a correggerlo senza riscriverlo.
Cos'è
history mostra la cronologia dei comandi digitati nella shell. In bash, la shell predefinita di quasi tutte le distribuzioni, la cronologia vive in due posti: in memoria, durante la sessione, e nel file ~/.bash_history, dove viene salvata quando la sessione termina e da cui viene riletta alla sessione successiva. Non è un programma a parte ma un comando interno della shell (come cd), e funziona insieme alle frecce, a Ctrl+R e a un gruppo di scorciatoie con il punto esclamativo, la cosiddetta history expansion.
Cosa fa
Elenca i comandi con un numero progressivo, permette di cercare tra quelli passati, di rieseguirne uno (o una parte) con poche battute e di cancellare le voci che non vuoi conservare. Il comportamento si regola con alcune variabili d'ambiente, di solito scritte in ~/.bashrc.
Come si usa
$ history [numero]
$ history [opzioni]Gli esempi sono per bash; con zsh molte cose funzionano allo stesso modo, ma il file è ~/.zsh_history e le impostazioni sono diverse.
Esempio 1: vedere la cronologia
$ history | tail -n 5
496 cd /var/www
497 ls -l
498 sudo nano /etc/nginx/nginx.conf
499 sudo nginx -t
500 history | tail -n 5
$ history 3
499 sudo nginx -t
500 history | tail -n 5
501 history 3Senza argomenti, history stampa tutta la cronologia, che può essere lunghissima: per questo si usa tail per vedere gli ultimi comandi o si passa a less. Con un numero (history 3) si vedono direttamente gli ultimi tre. Il numero a sinistra è l'identificativo del comando, che serve per rieseguirlo.
Esempio 2: cercare nella cronologia
$ history | grep nginx
455 sudo apt install nginx
498 sudo nano /etc/nginx/nginx.conf
499 sudo nginx -t
502 sudo systemctl reload nginx
$ history | grep -i "rsync" | tail -n 3
$ history | grep ssh | wc -l
14Combinando history con grep si ritrova un comando di cui si ricorda una parola. Con -i la ricerca ignora maiuscole e minuscole, con tail si limita ai più recenti, con wc -l si contano.
Esempio 3: la ricerca interattiva con Ctrl+R
(premi Ctrl+R e scrivi qualche lettera)
(reverse-i-search)`rsy': rsync -avz progetto/ web:/home/enzo/progetto/Ctrl+R è il modo più rapido: si premono i tasti e si comincia a scrivere una parte del comando, e la shell mostra l'ultimo comando che la contiene, aggiornandolo a ogni lettera. A quel punto:
- Invio esegue il comando trovato;
- freccia destra o Esc lo porta sulla riga per modificarlo senza eseguirlo;
Ctrl+Rancora una volta passa al risultato precedente (più vecchio);Ctrl+GoCtrl+Cannulla la ricerca.
Esempio 4: muoversi con le frecce e ripetere l'ultimo comando
Freccia su / Ctrl+P comando precedente
Freccia giù / Ctrl+N comando successivo
$ !! riesegue l'ultimo comando
$ !-2 riesegue il penultimo comandoCon le frecce si scorre la cronologia un comando alla volta e si può modificare prima di premere Invio. !! (due punti esclamativi) viene sostituito dall'ultimo comando, che è eseguito subito. !-2 è il penultimo, !-3 il terzultimo e così via.
Esempio 5: il classico "ho dimenticato sudo"
$ cat /etc/shadow
cat: /etc/shadow: Permesso negato
$ sudo !!
sudo cat /etc/shadow
root:$y$j9T$...:19650:0:99999:7:::
...È l'uso più comune di !!: sudo !! riesegue il comando appena fallito con i privilegi di amministratore. La shell stampa il comando espanso prima di eseguirlo, così vedi cosa sta per succedere. Controlla sempre che sia davvero il comando che volevi.
Esempio 6: eseguire un comando per numero o per inizio
$ !499
sudo nginx -t
nginx: configuration file /etc/nginx/nginx.conf test is successful
$ !sudo
sudo nginx -t
$ !?reload?
sudo systemctl reload nginx!499 esegue il comando numero 499 dell'elenco. !testo esegue l'ultimo comando che comincia con quel testo (qui !sudo), e !?testo? l'ultimo che lo contiene in qualsiasi punto. È comodo ma può sorprendere: con !ssh parte l'ultima connessione, qualunque fosse. Per vedere cosa verrebbe eseguito, aggiungi :p alla fine (!sudo:p): il comando viene solo stampato e inserito in cronologia.
Esempio 7: riusare gli argomenti
$ mkdir -p progetti/2026/ottobre
$ cd !$
cd progetti/2026/ottobre
$ ls /var/log/nginx/access.log
$ nano !$
nano /var/log/nginx/access.log
$ cp backup.tar.gz /mnt/disco/
$ ls -l !:1
ls -l backup.tar.gz!$ è l'ultimo argomento del comando precedente: perfetto per creare una cartella e poi entrarci. !:1 è il primo argomento e !* tutti. Esiste anche un modo con la tastiera: Alt+. (Alt e punto) inserisce l'ultimo argomento e, premuto più volte, risale ai precedenti. Rispetto a !$ ha il vantaggio che si vede il testo sulla riga prima di eseguirlo.
Esempio 8: correggere l'ultimo comando
$ sudo systemctl restart ngnix
Failed to restart ngnix.service: Unit ngnix.service not found.
$ ^ngnix^nginx
sudo systemctl restart nginx
$ !!:s/restart/status/
sudo systemctl status nginx^vecchio^nuovo riesegue l'ultimo comando sostituendo la prima occorrenza di vecchio con nuovo: ideale per correggere un errore di battitura. !!:s/a/b/ fa lo stesso in forma estesa, e con :gs/a/b/ si sostituiscono tutte le occorrenze. Per correzioni più grosse si può digitare fc, che apre l'ultimo comando nell'editor predefinito (per esempio nano) e lo esegue al salvataggio.
Esempio 9: data e ora dei comandi
$ export HISTTIMEFORMAT="%F %T "
$ history 3
502 2026-10-25 07:41:12 sudo systemctl reload nginx
503 2026-10-25 07:42:30 history 3
504 2026-10-25 07:43:01 history 3Per default la cronologia non registra l'orario. Impostando la variabile HISTTIMEFORMAT (con lo stesso formato di date) ogni comando mostra data e ora, utili per ricostruire "quando ho fatto quella modifica". Attenzione: i comandi eseguiti prima di aver impostato la variabile non hanno un orario e mostrano la data di avvio della sessione. Per renderla permanente va scritta in ~/.bashrc.
Esempio 10: cancellare una voce o tutta la cronologia
$ history -d 498
$ history -d 495-497
$ history -c
$ history -w
$ cat /dev/null > ~/.bash_historyhistory -d numero cancella una voce (e, nelle versioni recenti di bash, anche un intervallo come 495-497). history -c svuota la cronologia in memoria, ma il file ~/.bash_history resta com'era finché la sessione non termina o non si esegue history -w, che riscrive il file con il contenuto attuale. L'ultima riga svuota direttamente il file. Se hai scritto per sbaglio una password sulla riga di comando, il modo giusto è history -d sul numero giusto seguito da history -w: ma la password è già comparsa sullo schermo e può comparire altrove (vedi più avanti).
Esempio 11: impostare una cronologia più utile in ~/.bashrc
$ tail -n 7 ~/.bashrc
HISTSIZE=10000
HISTFILESIZE=20000
HISTCONTROL=ignoreboth:erasedups
HISTIGNORE="ls:cd:pwd:exit:clear"
HISTTIMEFORMAT="%F %T "
shopt -s histappend
PROMPT_COMMAND="history -a; $PROMPT_COMMAND"
$ source ~/.bashrcCosa fa ciascuna riga:
HISTSIZE: quanti comandi tenere in memoria;HISTFILESIZE: quanti conservare nel file;HISTCONTROL=ignoreboth:erasedups: non salva i comandi duplicati consecutivi né quelli che iniziano con uno spazio, ed elimina dalla cronologia le copie più vecchie dello stesso comando;HISTIGNORE: elenco di comandi da non registrare;HISTTIMEFORMAT: data e ora, come visto prima;shopt -s histappend: alla chiusura la sessione aggiunge la sua cronologia al file, invece di sovrascriverlo;PROMPT_COMMAND="history -a; ...": salva ogni comando nel file subito dopo l'esecuzione, e non solo alla chiusura.
Con source ~/.bashrc le modifiche valgono subito nella sessione corrente. Molte distribuzioni hanno già in ~/.bashrc alcune di queste righe, con valori più bassi (HISTSIZE=1000): controlla prima di aggiungere duplicati.
Esempio 12: più terminali aperti
$ history -a
$ history -n
$ history -rOgni terminale ha la propria cronologia in memoria, scritta nel file solo alla chiusura. Con più finestre aperte, i comandi di una non compaiono nelle altre. Con history -a si salva subito nel file la cronologia della sessione, con history -n si leggono nella sessione corrente i comandi aggiunti da altre finestre, e con history -r si rilegge tutto il file. La riga PROMPT_COMMAND dell'esempio precedente automatizza il salvataggio, non la lettura dalle altre finestre.
Esempio 13: statistiche e uso negli script
$ history | awk '{print $2}' | sort | uniq -c | sort -nr | head -n 5
132 ls
87 cd
64 sudo
41 nano
29 systemctl
$ awk '{print $1}' ~/.bash_history | sort | uniq -c | sort -nr | head -n 3Con le pipe si scopre quali sono i comandi che usi di più (vedi awk, sort e uniq). Il primo esempio funziona solo se la cronologia non ha l'orario: con HISTTIMEFORMAT impostato il comando si sposta in un'altra colonna. Il secondo legge direttamente il file e non ha questo problema, ma include solo i comandi già salvati.
Negli script la cronologia non è disponibile: history funziona solo nelle shell interattive, e un file di script ne ha una propria, vuota. Per analizzare la cronologia da uno script si legge il file:
#!/bin/bash
FILE="${1:-$HOME/.bash_history}"
echo "Comandi più usati in $FILE:"
awk '{print $1}' "$FILE" | sort | uniq -c | sort -nr | head -n 10Se il file ha le date (con HISTTIMEFORMAT attivo, bash scrive righe come #1792886400 prima di ciascun comando), il conteggio le considererà come comandi. Per ignorarle si aggiunge un filtro: grep -v '^#' "$FILE" | awk ....
Opzioni utili
history N: ultimi N comandi.-c: svuota la cronologia in memoria.-d N: cancella la voce N (o un intervalloN-M).-a: aggiunge al file i comandi di questa sessione;-w: riscrive il file con la cronologia in memoria.-r: rilegge il file;-n: legge solo le righe nuove.-p ...e:p: mostra senza eseguire (utile con la expansion).- Scorciatoie:
!!,!N,!-N,!testo,!?testo?,!$,!:N,!*,^a^b. - Tasti:
Ctrl+R(cerca all'indietro),Ctrl+S(in avanti, se il terminale non la usa per sospendere l'output),Alt+.(ultimo argomento),Ctrl+P/Ctrl+N. - Variabili:
HISTSIZE,HISTFILESIZE,HISTFILE,HISTCONTROL,HISTIGNORE,HISTTIMEFORMAT. fc: apre un comando precedente nell'editor;fc -lelenca.
Attenzione a
- La cronologia conserva tutto quello che scrivi, password e token compresi, se li hai digitati nella riga di comando (
mysql -p'segreto',curl -u utente:password,export TOKEN=...). Il file~/.bash_historyè leggibile da chi accede al tuo account e dagli amministratori. Meglio far chiedere la password al programma, o leggerla da un file protetto; per un comando che contiene dati riservati, scrivi uno spazio all'inizio (funziona seHISTCONTROLcontieneignorespaceoignoreboth: controllalo conecho $HISTCONTROL). - La cronologia viene scritta alla chiusura della shell: se il terminale si blocca, il computer si spegne o chiudi con
kill, i comandi della sessione possono andare persi. Conhistory -ao la rigaPROMPT_COMMANDsi salvano subito. - Senza
histappendl'ultima sessione che si chiude vince: con più terminali aperti, ciascuno riscrive il file e cancella i comandi degli altri. Conshopt -s histappendi comandi si aggiungono. - Il punto esclamativo è speciale: dentro le virgolette doppie viene interpretato come history expansion. Una frase come
echo "Ciao!"può dare l'erroreevent not found. Usa gli apici singoli (echo 'Ciao!') o disattiva la funzione conset +H. Negli script non è attiva. sudo !!esegue davvero il comando di prima: è comodo, ma se l'ultimo comando erarmcon un percorso sbagliato, lo ripeti con più privilegi. Leggi la riga che appare prima dell'esecuzione, o aggiungi:pper vederla soltanto.!testosceglie l'ultimo comando che comincia così, e può non essere quello che hai in mente. Per i comandi distruttivi (!rm,!dd) è una cattiva abitudine: usaCtrl+R, che mostra il comando prima di eseguirlo.history -cnon basta a cancellare: svuota la memoria, ma il file resta. Serve anchehistory -w, oppure svuotare il file. E alla chiusura, sehistappendè attivo, le righe già presenti nel file non vengono comunque toccate.- La cronologia non è un registro di sicurezza: ciascun utente ha la sua, la può modificare o cancellare, e non registra i comandi eseguiti dentro altri programmi (come un editor o una sessione
mysql, che hanno una cronologia propria, per esempio~/.mysql_history). Doposudo -iosusi lavora nella cronologia diroot. Per un controllo vero su un server servono strumenti comeauditd. - Il limite delle dimensioni: con
HISTSIZEeHISTFILESIZEbassi (il valore tipico è 1000 o 2000) i comandi più vecchi spariscono. Se vuoi conservare tutto per anni, alza i valori o imposta un valore vuoto e archivia il file periodicamente. - I comandi con a capo: un comando su più righe (con la barra inversa o con un ciclo
for) viene salvato come riga unica o spezzato, secondo l'impostazionecmdhist/lithist. Prima di rieseguirlo controlla che sia intero. - Altre shell, altre regole:
zshusa~/.zsh_historye opzioni comesetopt SHARE_HISTORY;fishha un proprio sistema (historycon altre opzioni). Le scorciatoie con!funzionano inbashezsh, non infish. - Sul server vale quanto vale il tuo utente: ogni utente ha la sua cronologia. Per rivedere cosa ha fatto un collega con l'accesso condiviso non basta
history: dopo unsudoil comando compare anche nel registro di sistema (/var/log/auth.logsu Debian e Ubuntu).
Riepilogo
| Comando / tasto | Cosa fa |
|---|---|
history | Mostra tutta la cronologia numerata |
history 20 | Mostra gli ultimi 20 comandi |
history | grep testo | Cerca un comando nella cronologia |
Ctrl+R | Ricerca interattiva all'indietro |
!! | Riesegue l'ultimo comando |
sudo !! | Riesegue l'ultimo comando con sudo |
!N | Riesegue il comando numero N |
!testo | Riesegue l'ultimo comando che inizia così |
!$ / Alt+. | Ultimo argomento del comando precedente |
^errato^corretto | Corregge e riesegue l'ultimo comando |
history -d N | Cancella una voce |
history -c | Svuota la cronologia in memoria |
history -a / -w | Salva nel file / riscrive il file |
HISTTIMEFORMAT="%F %T " | Mostra data e ora dei comandi |
HISTCONTROL=ignoreboth | Non registra duplicati e comandi con lo spazio iniziale |
fc | Modifica l'ultimo comando nell'editor |