User Tools

Site Tools


medium-unix:capitole:capitol-06

6. Înlănțuirea comenzilor

Comenzile în shell pot fi înlănțuite pentru a obține noi funcționalități. Anumite comenzi în shell pot primi diverse argumenter pentru a le altera funcționarea, în vreme ce altele primesc informații la standard input. Un one liner poate combina funcționalități precum folosirea operatorului | (pipe) sau expandarea comenzii ($(...)) pentru a crea rapid noi funcționalități în linia de comandă.

Subiecte abordate

  • Operatorul |
  • Comanda for
  • One linere
  • Filtre de text
  • Expresii regulate

Utilitare folosite

  • for
  • grep, tr, cut
  • basename
  • dd, split

Resurse utile

  • TODO
  • TODO

Slide-uri

Exerciții

Recapitulare

Expandare comenzi (creare arhive)

Creați o arhivă .tar.gz cu toate fișierele din /usr/include mai mari de 10KB.

Creați o arhivă .zip cu toate fișierele din /usr/include mai mari de 10KB.

Creați o arhivă .zip cu toate fișierele din /usr/include mai mari de 10KB accesate în ultimele 3 zile.

Pentru accesare în ultimele 3 zile, folosiți opțiunea -atime a comenzii find.

Informații despre dispozitive de tip caracter

Pentru dispozitivele de tip caracter din /dev afișați numele, majorul și minorul.

Folosiți find cu opțiunea -type și parametrul corespunzător pentru a extrage dispozitivele de tip caracter.

Folosiți stat cu opțiunile de formatare corespunzătoare și expandarea comenzii ($(...)) în conjuncție cu comanda find pentru afișarea numelui, majorului și minorului.

Bonus: Sortați-le în funcție de major.

Pentru sortare folosiți comanda sort. Va trebui să specificați separatorul de câmpuri (folosind opțiunea -t) și cheia de sortare (folosind opțiunea -k). Pentru că avem cheie de sortare un număr va trebui să faceți sortare numerică.

Alte informații despre dispozitive de tip caracter

Câte dispozitive de tip caracter se găsesc în fiecare director din ierarhia /dev?

Folosiți find pentru a extrage dispozitivele de tip caracter.

Folosiți dirname și expandarea comenzii ($(...)) în conjuncție cu comanda find de mai sus pentru a extrage doar numele directoarelor.

Prelucrați output-ul de mai sus prin comanda sort pentru a-l sorta.

Apoi folosiți output-ul astfel prelucrat prin comanda uniq cu opțiunea -c pentru a afișa numărul de apariții al fiecărui director.

Neajunsuri expandare comandă

Neajunsuri ale expandării comenzii vs find cu -exec și vs xargs (și vs for)

Demo-uri

Demo: Folosire filtre de bază

Folosire head, tail, sort, uniq, cut, tr, wc

Generare parolă random

Prelucrare date datornici

Demo: Expresii regulate

Exemple de expresii regulate

Câte directive #include conțin fișierele din /usr/include? Câte directive #include conțin fișierele de tip header C++ (.hpp)?

Demo: Folosire avansată grep și sort

Afișați fișierele din ierarhia /usr/include în ordinea numărului de apariții ale cuvântului FILE.

Demo: Folosire ''for''

for u in ana bogdan corina dan elena; do echo "user is $u"; done

Demo: Creare directoare în home-urile mai multor utilizatori

Pentru început adăugați în sistem utilizatorii ana, bogdan, corina, dan și elena folosind utilitarul adduser:

sudo adduser ana
sudo adduser bogdan
...

Ca root, parcurgeți utilizatorii sistemului care au home-ul în /home/, și creați un director public_html în home-ul fiecăruia.

Ca să extragem utilizatorii al căror director home este în /home/ folosim o construcție de forma

grep '/home/' /etc/passwd

Apoi filtrăm output-ul comenzii de mai sus cu ajutorul comenzii cut pentru a extrage doar prima coloană.

Apoi folosiți for și expandarea comenzii în forma

for user in $(grep ...); do ...; done

Realizați apoi un one-liner sau un script care să șteargă directorul public_html.

Pentru a verifica prezența/absența directorului folosiți comanda

ls -ld <path/to/folder>

unde <path/to/folder> este calea către directorul pe care dorim să-l verificăm.

Pentru afișarea tuturor directoarelor public_html din home-urile utilizatorilor puteți folosi un glob în forma

ls -ld /home/*/public_html/

Creare directoare și schimbare permisiuni

Ca root, parcurgeți utilizatorii sistemului care au home-ul în /home/, și creați un director public_html în home-ul fiecăruia. Schimbați ownership-ul acelui director la utilizator folosind chown.

Comanda chown este rulată doar de root, adică folosiți sudo.

O formă de rulare a comenzii chown este

sudo chown <username> <path/to/file>

unde <username> este numele utilizatorului către care vrem să schimbăm ownership-ul iar <path/to/file> este calea către fișierul/directorul pentru care vrem să schimbăm ownership-ul.

Pentru a verifica dacă a fost schimbat ownership-ul pe un director folosiți o construcție de forma

ls -ld <path/to/folder>

unde <path/to/folder> este calea către directorul pentru care dorim să verificăm ownership-ul.

Pentru afișarea de informații despre directoarele public_html din home-urile utilizatorilor puteți folosi un glob în forma

ls -ld /home/*/public_html/

Numele paginilor de manual dintr-o anumită secțiune

Afișați numele paginilor de manual din secțiunea 5. Numele sunt partea fără extensie din fișierele existente în directorul /usr/share/man/man5/. De exemplu, pentru fișierul issue.5.gz, numele este issue.

Recomandăm pașii de mai jos.

Construiți glob-ul care să afișeze toate fișierele cu extensia .5.gz din directorul /usr/share/man/man5/.

Nu este nevoie să folosiți find, puteți folosi un glob.

Folosiți comanda basename pentru a extrage doar numele de bază al fișierului.

Comanda basename ca argumente numele fișierulelor. Pentru a elimina extensia folosiți opțiunea -s a comenzii basename.

Opțiunea -s a comenzii basename primește ca argument extensia ce trebuie scoasă. Trebuie să scoateți extensia 5.gz.

Din lista de mai sus, extrageți doar comenzile care încep cu o anumită literă. Adică din outputul de mai sus, folosiți o comandă de forma grep '^a' pentru a extrage liniile care încep cu litera a folosind grep.

Afișare informații despre fișiere

Dorim să afișăm informații despre fișiere folosind comanda stat, comandă dedicată exact obținerii de informații despre fișiere.

Afișați pentru fișierul /etc/passwd doar dimensiunea. Indicație: Folosiți comanda stat împreună cu opțiunea --format (sau -c, forma scurtă a acestei opțiuni).

Afișați pentru fișierul /etc/passwd inode-ul, dimensiunea și uid-ul, separate prin , (virgulă).

Afișați numele, inode-ul, dimensiunea și uid-ul separate prin , (virgulă) pentru fișierele din ierarhia /etc/.

Afișați numele, inode-ul, dimensiunea și uid-ul separate prin , (virgulă) pentru fișierele din ierarhia /etc/ care au extensia .conf.

Calculați totalul de octeți ocupat de fișierele din ierarhia /etc/ care au extensia .conf.

Dacă aveți numere (câte unul pe linie) pe care vreți să le adunați, folosiți construcția filtrați output-ul prin comanda paste -s -d '+'. Adică ceva de forma

stat ... | paste -s -d '+'

Output-ul comenzii de mai sus este acum o expresie aritmetică ce poate fi evaluată. Comanda paste -s -d '+' serializează liniile (opțiunea -s) punând între ele caracterul + (pentru adunare).

Pentru a efectua calculul, filtrați expresia aritmetică folosită mai sus prin comanda bc. Comanda bc (un calculator în linia de comandă) primește o expresia aritmetică la standard input și o afișează la standard output. Adică o constructție de forma

stat  ... | paste -s -d '+' | bc

Fișiere ordonate după dimensiune

Listați primele 10 fișiere obișnuite (regular files) din ierarhia /etc (adică din toate directoarele, subdirectoarele și subdirectoarele acestora etc.) sortate în ordinea dimesiunii ocupate de fiecare fișier.

Folosiți find pentru a extrage fișierele. Apoi folosiți expandarea comenzii și stat pentru a afișa doar numele și dimensiunea fișierului. Adică o construcție de forma

stat -c ... $(find ...)

Apoi filtrați output-ul comenzii de mai sus cu ajutorul comenzii sort pentru a sorta numeric în funcție de dimensiunea fișierului. Adică o construcție de forma:

stat -c ... $(find ...) | sort ...

Apoi filtrați output-ul prin comanda tail pentru a extrage doar primele 10 fișiere, în ordinea dimensiunii. Adică o construcție de forma:

stat -c ... $(find ...) | sort ... | tail

Construire fișier cu informații binare

Creați un fișier care să conțină 2048 de octeți de zero (din /dev/zero) urmați de 2048 de octeți aleatori (din /dev/urandom) urmați de 2048 de octeți de zero și apoi urmați de 2048 de octeți din fișierul /bin/false de la offsetul 4096 al fișierului.

Folosim opțiunile skip și seek ale dd pentru a putea sări peste regiuni din fișierul de la intrare și din fișierul de la ieșire. Mai multe informații mai jos.

Sintaxa comenzii poate fi la modul

dd if=/dev/zero of=myfile.out bs=512 count=4

Comanda de mai sus copiază din fișierul de intrare (if: input file) /dev/zero la fișierul de ieșire (of: output file) myfile.out, un număr (count) de 4 blocuri de dimensiune 512 (bs: block size).

Pentru exercițiul curent este recomandat să folosiți dimensiunea blocului de 2048 de octeți (bs=2048).

Ca să investigăm conținutul binar al unui fișier folosind comanda xxd într-o construcție de forma

xxd myfile.out

Output-ul este pe două zone: prima zonă (din stânga) sunt afișate datele în format hexazecimal, iar în a doua zonă (din dreapta) în format ASCII, acolo unde se poate.

Argumentul pentru opțiunile skip și seek ale comenzii dd este dat în număr de blocuri, nu în număr de octeți.

Opțiunea seek este pentru a sări peste zone din fișierul de ieșire, iar opțiunea skip este pentru a sări peste zone din fișierul din intrare.

Generare fișiere multiple și conținut aleator

Folosiți /dev/urandom, dd și split pentru a genera, într-un one liner, 100 de fișiere a câte 100 de octeți aleatori cu numele partXYZ.dat unde XYZ sunt valorile 000, 001, …, 099. Adică part000.dat, part001.dat, …, part099.dat.

Nu este nevoie să creați fișiere. Le creează comanda split.

Nu este nevoie de for, seq sau touch.

Pentru a genera 100 de fișiere a câte 100 de octeți va trebui să generați cu comanda dd conținut de 100 x 100 = 10000 (zece mii) de octeți.

dd poate scrie la standard output în absența opțiunii of.

split poate citi de la standard input dacă se folosește construcția - (semnul minus) pentru numele fișierului.

Adică veți trece output-ul comenzii dd în input-ul comenzii split.

Adică trebuie să aveți o construcție de forma

dd if=/dev/urandom bs=... count=... | split ... - <prefix>

Folosiți ca ultimele două argumente pentru comanda split construcția - (semnul minus) însemnând că citește de la standard input și <prefix> reprezentând prefixul pe care vreți să îl puneți fișierelor nou create, adică șirul part.

Pentru split trebuie să folosiți opțiunile care:

  • specifică cât de mulți octeți să fie în fiecare fișier generat
  • specifică prefixul fișierelor nou create (în cazul nostru part)
  • specifică sufixul suplimentar al fișierelor nou create (în cazul nostru .dat
  • specifică faptul că se folosește sufix numeric (XYZ este numeric)
  • specifică faptul că se folosește sufix pe 3 caractere (XYZ are trei caractere)

Căutare cu grep

Folosiți grep pentru a selecta alias-urile cu destinația de forma nume.prenume@gmail.com din fișierul aliases din arhiva capitolului. Intrările din fișierul aliases se consideră de forma alias: destinație.

Generare parole aleatoare

Folosiți conținutul fișierului /dev/urandom pentru a genera o parolă aleatoare de 16 caractere.

Folosiți comanda tr cu opțiunile -d și -c pentru a extrage doar caractere tipările (litere mici, litere mari, numere).

Folosiți comanda head cu opțiunea -c pentru a extrage doar 16 caractere din output-ul anterior.

Actualizați comanda de mai sus pentru a genera 20 de parola a câte 16 caractere.

Recomandăm să nu folosiți for (merge, dar vrem să folosim fold :-P). Vedeți indicațiile legate de folosirea comenzii fold de mai jos.

Comanda fold împarte informațiile primite la intrarea standard în linii pe care le afișează la ieșirea standard. Poate să extragă linii de dimensiune dată. Uzual se folosește în forma

<command> | fold

unde <command> este o comandă care generează informații pe care apoi să le prelucreze comanda fold.

Extrageți 20*16 = 320 caractere aleatoare și apoi folosiți comanda fold cu opțiunea -w pentru a le grupa în seturi de câte 16. Adică o construcție de forma

cat /dev/urandom | ... | fold -w 16

medium-unix/capitole/capitol-06.txt · Last modified: 2016/05/19 13:04 by razvan