cut ritaglia da ogni riga di un testo solo le parti che ti interessano: una colonna di un file CSV, il nome utente di /etc/passwd, i primi caratteri di ogni riga. È uno degli strumenti più usati nelle pipeline, in coda a comandi come grep o ls e prima di sort e uniq.
Cos'è
cut significa "taglia": come le forbici su un foglio, ritaglia una porzione di ogni riga. Fa parte del pacchetto GNU coreutils ed è un eseguibile (/usr/bin/cut), presente su qualsiasi distribuzione GNU/Linux.
Cosa fa
Legge uno o più file, o lo standard input, e per ogni riga stampa solo le parti richieste, che possono essere:
- dei campi (
-f), cioè pezzi separati da un carattere delimitatore, come le colonne di un CSV; - dei caratteri (
-c) in posizioni fisse, contando dall'inizio della riga; - dei byte (
-b).
Non modifica nulla nei file di partenza e non riordina né elabora il contenuto: taglia e basta.
Come si usa
$ cut [opzioni] [file...]Si sceglie sempre una modalità (-f, -c o -b) seguita da un elenco di posizioni, scritto così:
| Elenco | Significato |
|---|---|
3 | Solo il terzo elemento |
1,3 | Il primo e il terzo |
2-4 | Dal secondo al quarto |
2- | Dal secondo fino alla fine |
-3 | Dall'inizio fino al terzo |
1,3-5 | Combinazioni di quanto sopra |
La numerazione parte da 1, non da 0. Per gli esempi usiamo il file clienti.csv:
$ cat clienti.csv
nome,città,età
Mario,Salerno,42
Anna,Napoli,35
Luca,Avellino,28
Giulia,Salerno,31Esempio 1: estrarre una colonna
$ cut -d, -f1 clienti.csv
nome
Mario
Anna
Luca
GiuliaCon -d, (delimiter) si indica il carattere che separa i campi, qui la virgola; con -f1 (fields) si chiede il primo campo. Non serve lasciare uno spazio tra -d e il carattere.
Esempio 2: più colonne, intervalli e resto della riga
$ cut -d, -f1,3 clienti.csv
nome,età
Mario,42
Anna,35
Luca,28
Giulia,31
$ cut -d, -f2- clienti.csv
città,età
Salerno,42
Napoli,35
Avellino,28
Salerno,31Con -f1,3 si prendono il primo e il terzo campo; con -f2- dal secondo in poi. L'output usa lo stesso delimitatore dell'ingresso.
Esempio 3: tutto tranne un campo, con --complement
$ cut -d, -f2 --complement clienti.csv
nome,età
Mario,42
...L'opzione --complement (versione GNU) inverte la scelta: stampa tutto tranne i campi indicati.
Esempio 4: cambiare il delimitatore di uscita
$ cut -d, -f1-3 --output-delimiter=';' clienti.csv
nome;città;età
Mario;Salerno;42
Anna;Napoli;35
Luca;Avellino;28
Giulia;Salerno;31Con --output-delimiter si sceglie il separatore dei campi in uscita. Qui il CSV con le virgole diventa un CSV con il punto e virgola, il formato che la versione italiana di Excel e di LibreOffice si aspetta.
Esempio 5: i file di sistema, separati da due punti
$ cut -d: -f1,7 /etc/passwd | head -n 3
root:/bin/bash
daemon:/usr/sbin/nologin
bin:/usr/sbin/nologinNel file /etc/passwd ogni riga descrive un utente con campi separati da due punti: il primo è il nome, il settimo la shell di accesso. È l'esempio classico con cui si impara cut.
Esempio 6: i primi caratteri di ogni riga con -c
$ echo "Salerno" | cut -c1-3
Sal
$ echo "20261015" | cut -c1-4
2026
$ echo "20261015" | cut -c5-6
10
$ ls -l | cut -c1-10
totale 8
-rw-r--r--
drwxr-xr-xCon -c si lavora per posizione, utile con testi a larghezza fissa. L'ultimo esempio mostra solo i permessi, cioè i primi 10 caratteri di ls -l, come visto nell'articolo su chmod.
Esempio 7: contare quante volte compare un valore
$ tail -n +2 clienti.csv | cut -d, -f2 | sort | uniq -c | sort -nr
2 Salerno
1 Napoli
1 AvellinoLa catena parte da tail -n +2, che salta la riga di intestazione, estrae la colonna con cut, la ordina e conta le ripetizioni con sort | uniq -c e ordina la classifica. È lo schema già visto negli articoli su head e tail e su sort e uniq.
Esempio 8: gli indirizzi più frequenti in un log
$ cut -d' ' -f1 /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -n 3
1204 66.249.66.1
388 93.184.216.34
251 151.101.1.69Nel registro degli accessi di nginx, nel formato predefinito, il primo campo, separato da uno spazio, è l'indirizzo IP del visitatore. Con questa riga si ottiene la classifica degli indirizzi che hanno fatto più richieste (gli indirizzi qui sono d'esempio).
Esempio 9: i domini di un elenco di indirizzi e-mail
$ cut -d@ -f2 iscritti.txt | sort | uniq -c | sort -nrQui il delimitatore è la chiocciola: il secondo campo di ogni indirizzo è il dominio.
Esempio 10: l'ultimo campo con rev
$ echo "archivio.tar.gz" | rev | cut -d. -f1 | rev
gz
$ echo "/home/enzo/Documenti/relazione.pdf" | rev | cut -d/ -f1 | rev
relazione.pdfIl comando cut non sa contare dalla fine ("l'ultimo campo"). Un trucco è invertire ogni riga con rev, tagliare il primo campo e invertire di nuovo. Per i percorsi esistono anche basename e dirname.
Esempio 11: colonne separate da più spazi
Molti comandi (df, ps, ls -l) allineano le colonne con più spazi. Per cut ogni spazio è un delimitatore, quindi compaiono campi vuoti. Si risolve comprimendo prima gli spazi con tr -s:
$ df -h | tail -n +2 | tr -s ' ' | cut -d' ' -f1,5
tmpfs 1%
/dev/sda2 54%
tmpfs 0%
/dev/sda1 2%Con tr -s ' ' ogni sequenza di spazi diventa uno spazio solo; tail -n +2 toglie l'intestazione. L'articolo su df mostra le stesse colonne: qui si estraggono dispositivo e percentuale di uso. Per questi casi awk è più comodo, perché tratta già le sequenze di spazi come un unico separatore.
Esempio 12: il delimitatore di tabulazione
$ cut -f2 dati.tsv
$ cut -d $'\t' -f2 dati.tsvSe non indichi -d, il delimitatore predefinito è la tabulazione. Per scriverla esplicitamente in Bash si usa $'\t'.
Esempio 13: uso negli script
#!/bin/bash
CSV="${1:?Indica il file CSV}"
echo "Città e numero di clienti:"
tail -n +2 "$CSV" | cut -d, -f2 | sort | uniq -c | sort -nrLo script si lancia come ./citta.sh clienti.csv e, con il file d'esempio, stampa la stessa classifica dell'esempio 7. La costruzione ${1:?messaggio} interrompe lo script con un errore se manca l'argomento. Quando i campi da estrarre sono molti, in Bash è più chiaro leggerli in variabili:
while IFS=, read -r nome citta eta; do
echo "$nome abita a $citta"
done < <(tail -n +2 clienti.csv)Opzioni utili
-d carattere: delimitatore dei campi (un solo carattere; predefinito: tabulazione).-f elenco: seleziona i campi.-c elenco: seleziona i caratteri per posizione.-b elenco: seleziona i byte per posizione.-s: con-f, salta le righe che non contengono il delimitatore.--complement: seleziona tutto tranne ciò che è indicato (GNU).--output-delimiter=testo: delimitatore da usare in uscita (GNU).-z: separa le righe con il carattere nullo invece che con l'a capo (GNU).
Attenzione a
- Il delimitatore è un solo carattere:
cut -d', ' -f1dà l'erroreil delimitatore deve essere un singolo carattere. Per separatori di più caratteri usaawkosed. Le righe senza delimitatore vengono stampate intere, ed è un comportamento che sorprende:
$ printf 'a:b\nsenza\nc:d\n' | cut -d: -f2 b senza d $ printf 'a:b\nsenza\nc:d\n' | cut -d: -f2 -s b dCon
-squelle righe vengono scartate.- Gli spazi multipli sono tanti delimitatori: due spazi consecutivi creano un campo vuoto in mezzo. Comprimili prima con
tr -s ' 'oppure usaawk. Anche i nomi con spazi, in colonne come quelle dils -l, spezzano i campi. cutnon riordina i campi:cut -d, -f3,1stampa comunque prima il campo 1 e poi il 3, nell'ordine in cui compaiono. Per invertire l'ordine serveawk.- CSV complessi:
cutnon conosce le virgolette. Una riga come"Rossi, Mario",Salernoverrebbe spezzata anche dentro il nome. Per i CSV reali servono strumenti dedicati (per esempiocsvkito un linguaggio di scripting). - I caratteri accentati con
-c: nelle versioni GNU più diffuse,-cfunziona come-be conta i byte, non le lettere. In UTF-8 una "à" occupa due byte, quindiecho "città" | cut -c1-4può tagliare a metà la lettera e produrre un carattere rovinato (cit�). Con testi accentati usa i campi (-f) oppureawkosed. - I file di Windows: se il file termina le righe con
\r\n, l'ultimo campo si porta dietro un\rinvisibile, e il confronto con altri valori sembra non funzionare. Lo vedi concat -Ae lo togli contr -d '\r'. - Righe con meno campi del previsto: se chiedi il campo 5 e la riga ne ha 3,
cutstampa una riga vuota, senza segnalare errori. Controlla i dati conawk -F, '{print NF}'prima di fidarti dei risultati. - Numerazione da 1:
-f0è un errore. - Non è un editor:
cutscrive il risultato a schermo. Per salvarlo, reindirizza su un altro file; non scrivere sullo stesso file di ingresso, con>, perché lo svuoteresti.
Riepilogo
| Comando | Cosa fa |
|---|---|
cut -d, -f1 file | Primo campo, separato da virgole |
cut -d: -f1,7 file | Primo e settimo campo, separati da due punti |
cut -d, -f2- file | Dal secondo campo in poi |
cut -d, -f2 --complement file | Tutti i campi tranne il secondo |
cut -d, -f1-3 --output-delimiter=';' file | Cambia il separatore in uscita |
cut -c1-3 file | Primi tre caratteri di ogni riga |
cut -f2 file | Secondo campo, separato da tabulazioni |
cut -d: -f2 -s file | Ignora le righe senza delimitatore |
… | tr -s ' ' | cut -d' ' -f2 | Colonne separate da più spazi |
… | rev | cut -d. -f1 | rev | Ultimo campo di una riga |