
Usa le pipe Linux per coreografare il modo in cui collaborano le utility della riga di comando. Semplifica i processi complessi e aumenta la tua produttività sfruttando una raccolta di comandi autonomi e trasformandoli in un team unico. Ti mostriamo come.
I tubi sono ovunque
Le pipe sono una delle funzionalità della riga di comando più utili di Linux e sistemi operativi simili a Unix. I tubi vengono utilizzati in innumerevoli modi. Guarda qualsiasi articolo della riga di comando di Linux — su qualsiasi sito web, non solo sul nostro — e vedrai che le pipe appaiono più spesso. Ho esaminato alcuni degli articoli Linux di How-To Geek e le pipe sono usate in tutti, in un modo o nell'altro.
Le pipe di Linux consentono di eseguire azioni non supportate immediatamente dalla shell. Ma poiché la filosofia di progettazione di Linux è quella di avere molte piccole utility che eseguono molto bene la loro funzione dedicata e senza funzionalità inutili – il mantra “fai una cosa e fallo bene” – puoi far passare stringhe di comandi insieme a pipe in modo che l'output di un comando diventa l'input di un altro. Ogni comando che immetti porta il suo talento unico al team e presto scopri di aver messo insieme una squadra vincente.
Un semplice esempio
Supponiamo di avere una directory piena di molti diversi tipi di file. Vogliamo sapere quanti file di un certo tipo sono presenti in quella directory. Esistono altri modi per farlo, ma l'obiettivo di questo esercizio è introdurre le pipe, quindi lo faremo con le pipe.
Possiamo ottenere facilmente un elenco dei file usando ls:
ls

Per separare il tipo di file di interesse, utilizzeremo grep. Vogliamo trovare i file che hanno la parola “pagina” nel loro nome file o estensione del file.
Useremo il carattere speciale della shell “|“Per convogliare l'uscita da ls in grep.
ls | grep "page"

grep stampa le linee che corrispondono al suo modello di ricerca. Quindi questo ci dà un elenco contenente solo file “.page”.

Anche questo banale esempio mostra la funzionalità dei tubi. L'output di ls non è stato inviato alla finestra del terminale. È stato inviato a grep come dati per il grep comando con cui lavorare. L'output che vediamo proviene grep, che è l'ultimo comando in questa catena.
Estensione della nostra catena
Iniziamo ad estendere la nostra catena di comandi inoltrati. Possiamo contare i file “.page” aggiungendo il wc comando. Useremo il -l (conteggio righe) con wc. Nota che abbiamo anche aggiunto il -l (formato lungo) opzione a ls . Lo useremo tra poco.
ls - | grep "page" | wc -l

grep non è più l'ultimo comando della catena, quindi non ne vediamo l'output. L'output di grep viene inserito nel file wc comando. L'output che vediamo nella finestra del terminale proviene da wc. wc segnala che ci sono 69 file “.page” nella directory.
Estendiamo di nuovo le cose. Prenderemo il wc comando dalla riga di comando e sostituirlo con awk. Ci sono nove colonne nell'output di ls con il -l (formato lungo) opzione. Useremo awk per stampare le colonne cinque, tre e nove. Queste sono le dimensioni, il proprietario e il nome del file.
ls -l | grep "page" | awk '{print $5 " " $3 " " $9}'

Otteniamo un elenco di quelle colonne, per ciascuno dei file corrispondenti.

Ora passeremo quell'output attraverso sort comando. Useremo il -n (numerico) opzione da lasciare sort sapere che la prima colonna dovrebbe essere trattata come un numero.
ls -l | grep "page" | awk '{print $5 " " $3 " " $9}' | sort -n

L'output è ora ordinato in ordine di dimensione del file, con la nostra selezione personalizzata di tre colonne.

Aggiunta di un altro comando
Concluderemo aggiungendo il tail comando. Gli diremo di elencare solo le ultime cinque righe di output.
ls -l | grep "page" | awk '{print $5 " " $3 " " $9}' | sort -n | tail -5

Questo significa che il nostro comando si traduce in qualcosa come “mostrami i cinque file” .page “più grandi in questa directory, ordinati per dimensione.” Ovviamente, non esiste alcun comando per farlo, ma usando le pipe, abbiamo creato il nostro. Potremmo aggiungere questo o qualsiasi altro comando lungo come alias o funzione shell per salvare tutta la digitazione.
Ecco l'output:

Potremmo invertire l'ordine delle dimensioni aggiungendo il -r (inversa) all'opzione sort comando e utilizzo head invece di tail per selezionare le linee dalla parte superiore dell'output.
Questa volta i cinque file “.page” più grandi sono elencati dal più grande al più piccolo:

Alcuni esempi recenti
Ecco due esempi interessanti da recenti articoli How-To geek.
Alcuni comandi, come il xargscomando, sono progettati per avere l'input reindirizzato a loro. Ecco un modo in cui possiamo avere wc contare le parole, i caratteri e le righe in più file, tramite il piping ls in xargs che quindi alimenta l'elenco dei nomi dei file a wc come se fossero stati passati a wc come parametri della riga di comando.
ls *.page | xargs wc

I numeri totali di parole, caratteri e righe sono elencati nella parte inferiore della finestra del terminale.

Ecco un modo per ottenere un elenco ordinato delle estensioni di file univoche nella directory corrente, con un conteggio di ciascun tipo.
ls | rev | cut -d'.' -f1 | rev | sort | uniq -c

C'è molto da fare qui.
- ls: Elenca i file nella directory
- rev: Inverte il testo nei nomi dei file.
- tagliare: Taglia la stringa alla prima occorrenza del delimitatore specificato “.”. Il testo dopo questo viene scartato.
- rev: Inverte il testo rimanente, che è l'estensione del nome file.
- ordinare: Ordina l'elenco in ordine alfabetico.
- uniq: Conta il numero di ciascuna voce univoca nell'elenco.
L'output mostra l'elenco delle estensioni di file, in ordine alfabetico con un conteggio di ciascun tipo univoco.

Tubi con nome
C'è un altro tipo di pipe a nostra disposizione, chiamato named pipe. Le pipe negli esempi precedenti vengono create al volo dalla shell quando elabora la riga di comando. Le pipe vengono create, utilizzate e quindi eliminate. Sono transitori e non lasciano traccia di se stessi. Esistono solo finché il comando che li utilizza è in esecuzione.
Le pipe con nome appaiono come oggetti persistenti nel filesystem, quindi puoi vederle usando ls. Sono persistenti perché sopravvivranno al riavvio del computer, anche se i dati non letti in quel momento verranno eliminati.
Le pipe nominate sono state usate molto contemporaneamente per consentire a diversi processi di inviare e ricevere dati, ma non li vedo usati così da molto tempo. Senza dubbio ci sono persone là fuori che le usano ancora con grande efficacia, ma non ne ho mai avuto di recente. Ma per completezza, o solo per soddisfare la tua curiosità, ecco come puoi usarli.
Le pipe denominate vengono create con mkfifo comando. Questo comando creerà una pipe denominata chiamata “geek-pipe” nella directory corrente.
mkfifo geek-pipe

Possiamo vedere i dettagli della pipa denominata se usiamo il file ls comando con il -l (formato lungo) opzione:
ls -l geek-pipe

Il primo carattere della lista è una “p”, nel senso che è una pipe. Se fosse una “d”, significherebbe che l'oggetto del file system è una directory e un trattino “-” significherebbe che è un file normale.
Utilizzando la pipa denominata
Usiamo la nostra pipa. Le pipe senza nome che abbiamo usato nei nostri esempi precedenti hanno passato immediatamente i dati dal comando di invio al comando di ricezione. I dati inviati tramite una pipe denominata rimarranno nella pipe fino a quando non vengono letti. I dati sono effettivamente conservati in memoria, quindi la dimensione della pipe denominata non varierà ls elenchi se ci sono dati o meno.
In questo esempio utilizzeremo due finestre di terminale. Userò l'etichetta:
# Terminal-1
in una finestra terminale e
# Terminal-2
nell'altro, così puoi differenziarli. L'hash “#” dice alla shell che ciò che segue è un commento e di ignorarlo.
Prendiamo l'intero esempio precedente e reindirizziamolo nella pipa denominata. Quindi stiamo usando sia le pipe senza nome che quelle con nome in un solo comando:
ls | rev | cut -d'.' -f1 | rev | sort | uniq -c > geek-pipe

Non succederà molto. Tuttavia potresti notare che non verrai reindirizzato al prompt dei comandi, quindi qualcosa sta succedendo.
Nell'altra finestra del terminale, emettere questo comando:
cat < geek-pipe
<img class = "alignnone size-full wp-image-439186" src = "https://www.howtogeek.com/wp-content/uploads/2019/09/20.png" alt = "cat < geek-pipe in a terminal window" width="646" height="77" onload="pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);" onerror="this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);">
Stiamo reindirizzando il contenuto della pipe denominata in cat, così che cat visualizzerà quel contenuto nella seconda finestra del terminale. Ecco l'output:

E vedrai che sei tornato al prompt dei comandi nella prima finestra del terminale.

Quindi, cosa è appena successo.
- Abbiamo reindirizzato un po 'di output nella pipe denominata.
- La prima finestra del terminale non è tornata al prompt dei comandi.
- I dati sono rimasti nella pipe fino a quando non sono stati letti dalla pipe nel secondo terminale.
- Siamo stati restituiti al prompt dei comandi nella prima finestra del terminale.
Potresti pensare di poter eseguire il comando nella prima finestra del terminale come attività in background aggiungendo un & fino alla fine del comando. E avresti ragione. In tal caso, saremmo stati immediatamente restituiti al prompt dei comandi.
Il punto di non l'utilizzo dell'elaborazione in background era per evidenziare che una pipe denominata è a processo di blocco. Mettere qualcosa in una pipa denominata apre solo un'estremità della pipa. L'altra estremità non viene aperta fino a quando il programma di lettura non estrae i dati. Il kernel sospende il processo nella prima finestra del terminale fino a quando i dati non vengono letti dall'altra estremità della pipe.
Il potere dei tubi
Al giorno d'oggi, le pipe denominate sono qualcosa di nuovo.
Le vecchie pipe Linux semplici, d'altra parte, sono uno degli strumenti più utili che puoi avere nel tuo toolkit della finestra del terminale. La riga di comando di Linux inizia a prendere vita per te e ottieni un power-up completamente nuovo quando puoi orchestrare una raccolta di comandi per produrre una performance coerente.
Suggerimento per la divisione: è meglio scrivere i comandi inoltrati aggiungendo un comando alla volta e facendo funzionare quella parte, quindi eseguendo il piping nel comando successivo.

