Cum să utilizați pipe pe Linux

Folosiți conductele în Linux pentru a orchestra colaborarea dintre utilitarele liniei de comandă. Simplificați sarcinile complexe și sporiți productivitatea utilizând o serie de comenzi individuale, transformându-le într-o echipă puternică. Vă vom explica cum.

Conductele sunt omniprezente

Conductele reprezintă una dintre cele mai valoroase caracteristici ale liniei de comandă din sistemele de operare Linux și Unix. Acestea sunt utilizate într-o varietate mare de moduri. Dacă analizați orice articol referitor la linia de comandă Linux – pe orice site, nu doar pe al nostru – veți observa că conductele apar frecvent. După o revizuire a câtorva articole Linux de pe How-To Geek, am constatat că conductele sunt folosite în mod constant.

Conductele Linux vă permit să efectuați acțiuni ce nu sunt disponibile în mod implicit de către shell. Întrucât filozofia de design Linux se bazează pe existența unor utilitare mici, fiecare îndeplinind o singură funcție foarte bine, fără funcționalități inutile – adică deviza „fă un lucru și fă-l bine” – aveți posibilitatea de a lega serii de comenzi prin conducte. În acest mod, ieșirea unei comenzi devine intrarea următoarei. Fiecare comandă aduce cu sine abilitățile sale unice, și astfel veți constata că ați construit o echipă de succes.

Un exemplu elementar

Să presupunem că avem un director plin cu diverse tipuri de fișiere. Scopul este să aflăm câte fișiere de un anumit tip există în acel director. Există și alte metode de a realiza acest lucru, dar scopul nostru este să înțelegem funcționarea conductelor, așa că le vom utiliza.

Putem obține simplu o listă a fișierelor folosind comanda ls:

ls

Pentru a selecta tipul de fișier de interes, vom folosi grep. Intenția noastră este să găsim fișiere care includ cuvântul „page” în denumirea sau extensia lor.

Vom folosi caracterul special al shell-ului „|” pentru a direcționa ieșirea de la ls către grep.

ls | grep "page"

grep afișează liniile care se potrivesc cu modelul de căutare. Astfel, obținem o listă care conține doar fișierele cu extensia „.page”.

Chiar și acest exemplu simplu ilustrează funcționalitatea conductelor. Ieșirea comenzii ls nu a fost afișată în fereastra terminalului. A fost trimisă către grep ca date de procesat. Rezultatul pe care îl vedem provine de la grep, care este ultima comandă din acest lanț.

Extinderea lanțului

Acum să începem să extindem lanțul nostru de comenzi conectate prin conducte. Putem număra fișierele „.page” adăugând comanda wc. Vom folosi opțiunea -l (număr de linii) cu wc. De asemenea, am adăugat și opțiunea -l (format lung) la ls. O vom folosi în curând.

ls -l | grep "page" | wc -l

grep nu mai este ultima comandă din lanț, așadar nu-i vedem rezultatul. Ieșirea de la grep este transferată către comanda wc. Rezultatul afișat în fereastra terminalului este generat de wc. Aceasta raportează că există 69 de fișiere „.page” în director.

Să ducem lucrurile mai departe. Vom înlocui comanda wc din linia de comandă cu awk. Rezultatul de la ls cu opțiunea -l (format lung) conține nouă coloane. Vom folosi awk pentru a afișa coloanele cinci, trei și nouă. Acestea corespund dimensiunii, proprietarului și numelui fișierului.

ls -l | grep "page" | awk '{print $5 " " $3 " " $9}'

Obținem o listă cu aceste coloane, pentru fiecare dintre fișierele care se potrivesc criteriilor.

Acum vom direcționa această ieșire prin comanda sort. Vom folosi opțiunea -n (numeric) pentru a indica sortării că prima coloană trebuie tratată ca numere.

ls -l | grep "page" | awk '{print $5 " " $3 " " $9}' | sort -n

Acum, rezultatul este sortat în funcție de dimensiunea fișierului, incluzând cele trei coloane selectate de noi.

Adăugarea unei alte comenzi

Pentru a finaliza, vom adăuga comanda tail. Îi vom spune să afișeze doar ultimele cinci linii din ieșire.

ls -l | grep "page" | awk '{print $5 " " $3 " " $9}' | sort -n | tail -5

Această comandă se traduce prin: „arată-mi cele mai mari cinci fișiere „.page” din acest director, sortate după dimensiune”. Evident, nu există o singură comandă pentru a obține acest lucru, dar prin utilizarea conductelor, am creat-o noi. Această comandă – sau orice altă comandă lungă – ar putea fi adăugată ca alias sau funcție de shell pentru a evita tastarea repetată.

Iată rezultatul:

Am putea inversa ordinea dimensiunilor adăugând opțiunea -r (invers) la comanda sort și folosind head în loc de tail pentru a selecta liniile de la începutul ieșirii.

De această dată, cele mai mari cinci fișiere „.page” sunt listate în ordine descrescătoare a dimensiunii:

Câteva exemple recente

Vă prezentăm două exemple interesante din articole recente despre tehnologie.

Unele comenzi, cum ar fi xargs, sunt concepute pentru a primi intrare. Iată o modalitate de a utiliza wc pentru a număra cuvinte, caractere și rânduri în mai multe fișiere, direcționând ieșirea ls către xargs, care apoi trimite lista de nume de fișiere către wc, ca și cum ar fi fost specificate ca parametri în linia de comandă.

ls *.page | xargs wc

Numărul total de cuvinte, caractere și linii este afișat în partea de jos a ferestrei terminalului.

Iată o modalitate de a obține o listă sortată a extensiilor de fișiere unice din directorul curent, cu un număr pentru fiecare tip.

ls | rev | cut -d'.' -f1 | rev | sort | uniq -c

Aici se întâmplă multe:

ls: Listează fișierele din director.
rev: Inversează textul din numele fișierelor.
cut: Elimină secvența de text până la prima apariție a delimitatorului „.”. Textul de după este eliminat.
rev: Inversează textul rămas, care este extensia numelui de fișier.
sort: Sortează lista în ordine alfabetică.
uniq: Numără numărul fiecărei intrări unice în listă.

Rezultatul afișează lista extensiilor de fișiere, sortate alfabetic, cu un număr pentru fiecare tip unic.

Conducte numite

Mai există un alt tip de conductă, denumit conductă numită. Conductele din exemplele anterioare sunt create dinamic de shell în timpul procesării liniei de comandă. Ele sunt create, utilizate și apoi eliminate, fiind tranzitorii și fără a lăsa urme. Ele există doar pe durata execuției comenzii care le utilizează.

Conductele numite apar ca obiecte persistente în sistemul de fișiere, putând fi vizualizate cu ajutorul comenzii ls. Sunt persistente deoarece supraviețuiesc repornirilor computerului, deși orice date necitite din ele la acel moment vor fi eliminate.

Conductele numite au fost folosite intens în trecut pentru a permite diferitelor procese să trimită și să primească date, dar nu le-am mai văzut folosite recent. Cu siguranță, există utilizatori care le folosesc în mod eficient, dar nu am întâlnit exemple recente. Pentru a fi complet, sau doar pentru a satisface curiozitatea, iată cum le puteți folosi.

Conductele numite se creează cu comanda mkfifo. Această comandă va crea o conductă numită „geek-pipe” în directorul curent.

mkfifo geek-pipe

Putem vedea detaliile conductei numite dacă folosim comanda ls cu opțiunea -l (format lung):

ls -l geek-pipe

Primul caracter din listă este „p”, indicând că este o conductă. Dacă ar fi „d”, ar însemna că obiectul sistemului de fișiere este un director, iar o liniuță „-” ar însemna că este un fișier obișnuit.

Utilizarea conductei numite

Să folosim conducta creată. Conductele anonime pe care le-am folosit în exemplele precedente trimiteau imediat datele de la comanda sursă la cea de destinație. Datele trimise printr-o conductă numită vor rămâne în ea până când sunt citite. Datele sunt stocate în memorie, așa că dimensiunea conductei numite nu se va modifica în listele ls, indiferent dacă există date în ea sau nu.

Pentru acest exemplu, vom utiliza două ferestre de terminal. Vom folosi eticheta:

# Terminal-1

într-o fereastră de terminal, și

# Terminal-2

în cealaltă, pentru a le diferenția. Caracterul „#” informează shell-ul că textul următor este un comentariu și trebuie ignorat.

Să luăm exemplul anterior și să-l redirecționăm către conducta numită. Așadar, vom folosi atât conducte anonime, cât și conducte numite într-o singură comandă:

ls | rev | cut -d'.' -f1 | rev | sort | uniq -c > geek-pipe

Aparent, nu se va întâmpla nimic. Veți observa că nu vă veți întoarce la prompterul de comandă, ceea ce sugerează că ceva se întâmplă.

În cealaltă fereastră de terminal, introduceți această comandă:

cat < geek-pipe

Redirecționăm conținutul conductei numite către cat, astfel încât aceasta să afișeze conținutul în a doua fereastră de terminal. Iată rezultatul:

Veți observa că v-ați întors la prompterul de comandă în prima fereastră de terminal.

Deci, ce s-a întâmplat mai exact:

Am redirecționat anumite rezultate către conducta numită.
Prima fereastră de terminal nu a revenit la prompterul de comandă.
Datele au rămas în conductă până când au fost citite din ea de către al doilea terminal.
Am revenit la prompterul de comandă în prima fereastră de terminal.

S-ar putea să vă gândiți că ați putea rula comanda din prima fereastră de terminal ca sarcină de fundal, adăugând un & la finalul comenzii. Și ați avea dreptate. În acest caz, am fi revenit imediat la prompterul de comandă.

Scopul de a nu folosi procesarea în fundal a fost acela de a sublinia faptul că o conductă numită este un proces blocant. Scrierea într-o conductă numită deschide doar un capăt al acesteia. Celălalt capăt rămâne închis până când programul de citire extrage datele. Kernel-ul suspendă procesul din prima fereastră de terminal până când datele sunt citite de la celălalt capăt al conductei.

Puterea conductelor

În zilele noastre, conductele numite sunt o raritate.

Pe de altă parte, conductele Linux simple, obișnuite, reprezintă unul dintre cele mai utile instrumente pe care le puteți avea la dispoziție în linia de comandă. Linia de comandă Linux începe să prindă viață și devine utilă atunci când aveți capacitatea de a orchestra o serie de comenzi pentru a produce o performanță coerentă.

Sugestie suplimentară: Cel mai bine este să creați comenzi cu conducte adăugând o comandă o dată, verificând funcționarea porțiunii, apoi adăugând următoarea comandă.