Come usare le pipe su Linux

Terminale Linux su un laptop
Fatmawati Achmad Zaenuri / Shutterstock.com

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

Raccolta di file in una directory, in una finestra del terminale

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"

ls -l | grep "page" in una finestra di terminale

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

elenco dei file di paging in una finestra terminale

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

ls - | grep "page" | wc -l in una finestra terminale

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}'

ls -l | grep

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

Elenco di tre colonne per ciascun file corrispondente in una finestra del terminale

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

ls -l | grep

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

File ordinati per dimensione in una finestra del terminale

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

ls -l | grep

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:

Cinque file .page più grandi elencati per ordine di dimensione in una finestra terminale

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.

ls -l | grep 

Questa volta i cinque file “.page” più grandi sono elencati dal più grande al più piccolo:

Cinque file .page più grandi elencati in ordine inverso in una finestra terminale

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

ls * .page | xargs wc in una finestra terminale

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

Conteggio di parole, caratteri e linee in una finestra 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

ls | rev | cut -d '.' -f1 | rev | ordina | uniq -c in una finestra terminale

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.

Elenco di estensioni di file univoche in una finestra terminale

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

mkfifo geek-pipe in una finestra terminale

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

ls -l geek-pipe

ls -l geek-pipe in una finestra terminale

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

ls | rev | cut -d '.' -f1 | rev | ordina | uniq -c> geek-pipe in una finestra terminale

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:

Il contenuto del piping nominato viene mostrato in una finestra del terminale

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

Compito completato e prompt dei comandi in una finestra 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.

Articoli correlati

Ultimi articoli