Cum să parcurgeți un arbore de director pe Linux
Publicat: 2022-07-21
Directoarele de pe Linux vă permit să grupați fișiere în colecții distincte, separate. Dezavantajul este că devine obositoare trecerea de la un director la altul pentru a efectua o sarcină repetitivă. Iată cum să automatizezi asta.
Totul despre directoare
Prima comandă pe care o înveți când ești introdus în Linux este probabil ls
, dar cd
nu va fi cu mult în urmă. Înțelegerea directoarelor și a modului de deplasare în jurul lor, în special subdirectoarele imbricate, este o parte fundamentală a înțelegerii modului în care Linux se organizează și a modului în care vă puteți organiza propria lucrare în fișiere, directoare și subdirectoare.
Înțelegerea conceptului de arbore de directoare – și a modului de deplasare între ele – este una dintre multele etape mici pe care le treceți pe măsură ce vă familiarizați cu peisajul Linux. Folosind cd
cu o cale te duce la acel director. Comenzile rapide precum cd ~
sau cd
singure vă duc înapoi la directorul dvs. de acasă, iar cd ..
vă mută la un nivel sus în arborele de directoare. Simplu.
Cu toate acestea, nu există un mijloc la fel de simplu de a rula o comandă în toate directoarele unui arbore de directoare. Există diferite moduri în care putem obține această funcționalitate, dar nu există o comandă Linux standard dedicată acestui scop.
Unele comenzi, cum ar fi ls
, au opțiuni de linie de comandă care le forțează să opereze recursiv , ceea ce înseamnă că încep într-un singur director și lucrează metodic prin întregul arbore de directoare de sub acel director. Pentru ls
, este opțiunea -R
(recursivă).
Dacă trebuie să utilizați o comandă care nu acceptă recursiunea, trebuie să furnizați singur funcționalitatea recursivă. Iată cum să faci asta.
RELATE: 37 de comenzi Linux importante pe care ar trebui să le cunoașteți
Comanda arborelui
Comanda tree
nu ne va ajuta cu sarcina la îndemână, dar face mai ușor să vedem structura unui arbore de directoare. Desenează arborele într-o fereastră de terminal, astfel încât să putem obține o imagine de ansamblu instantanee a directoarelor și subdirectoarelor care alcătuiesc arborele de directoare și a pozițiilor lor relative în arbore.
Va trebui să instalați tree
.
Pe Ubuntu trebuie să tastați:
arborele de instalare sudo apt
Pe Fedora, utilizați:
sudo dnf install tree
Pe Manjaro, comanda este:
sudo pacman -Sy tree
Utilizarea tree
fără parametri scoate arborele de sub directorul curent.
copac
Puteți trece o cale către tree
pe linia de comandă.
munca în copaci
Opțiunea -d
(directoare) exclude fișierele și arată doar directoare.
tree -d lucru
Acesta este cel mai convenabil mod de a obține o vedere clară a structurii unui arbore de directoare. Arborele de directoare prezentat aici este cel folosit în exemplele următoare. Există cinci fișiere text și opt directoare.
Nu analizați rezultatul de la ls pentru a traversa directoare
Primul tău gând ar putea fi, dacă ls
poate traversa în mod recursiv un arbore de directoare, de ce să nu folosești ls
pentru a face tocmai asta și să conducă rezultatul în alte comenzi care analizează directoarele și efectuează unele acțiuni?
Analizarea rezultatelor lui ls
este considerată o practică proastă. Datorită capacității Linux de a crea nume de fișiere și directoare care conțin tot felul de caractere ciudate, devine foarte dificil să se creeze un parser generic, universal corect.
S-ar putea să nu creați niciodată cu bună știință un nume de director atât de absurd ca acesta, dar o greșeală într-un script sau o aplicație ar putea.
Analizarea numelor de fișiere și directoare legitime, dar prost luate în considerare este predispusă la erori. Există și alte metode pe care le putem folosi, care sunt mai sigure și mult mai robuste decât ne bazam pe interpretarea rezultatului lui ls
.
Folosind comanda find
Comanda find
are capabilități recursive încorporate și, de asemenea, are capacitatea de a rula comenzi pentru noi. Acest lucru ne permite să construim o singură linie puternică. Dacă este ceva pe care probabil că veți dori să îl utilizați în viitor, vă puteți transforma linerul într-un alias sau într-o funcție shell.
Această comandă circulă recursiv prin arborele de directoare, căutând directoare. De fiecare dată când găsește un director, tipărește numele directorului și repetă căutarea în acel director. După ce a finalizat căutarea într-un director, iese din acel director și reia căutarea în directorul părinte.
find work -type d -execdir echo "In:" {} \;
Puteți vedea după ordinea în care sunt listate directoarele, cum progresează căutarea prin arbore. Comparând ieșirea de la comanda tree
cu ieșirea de la find
one-liner, veți vedea cum find
caută fiecare director și subdirector pe rând până când ajunge într-un director fără subdirectoare. Apoi merge înapoi la un nivel și reia căutarea la acel nivel.
Iată cum este alcătuită comanda.
- find : Comanda
find
. - lucru : directorul în care începe căutarea. Aceasta poate fi o cale.
- -type d : Căutăm directoare.
- -execdir : Vom executa o comandă în fiecare director pe care îl găsim.
- echo „În:” {} : Aceasta este comanda., Pur și simplu trimitem ecou numele directorului în fereastra terminalului. „{}” conține numele directorului curent.
- \; : Acesta este un punct și virgulă folosit pentru a termina comanda. Trebuie să scăpăm cu bara oblică inversă, astfel încât Bash să nu-l interpreteze direct.
Cu o ușoară modificare, putem face ca comanda find să returneze fișiere care se potrivesc cu un indiciu de căutare. Trebuie să includem opțiunea -name și un indiciu de căutare. În acest exemplu, căutăm fișiere text care se potrivesc cu „*.txt” și căutăm numele lor în fereastra terminalului.

find work -name "*.txt" -type f -execdir echo "Găsit:" {} \;
Dacă căutați fișiere sau directoare depinde de ceea ce doriți să obțineți. Pentru a rula o comandă în fiecare director , utilizați -type d
. Pentru a rula o comandă pe fiecare fișier care se potrivește , utilizați -type f
.
Această comandă numără liniile din toate fișierele text din directorul de pornire și subdirectoare.
găsiți lucru -nume "*.txt" -type f -execdir wc -l {} \;
LEGATE: Cum să utilizați comanda find în Linux
Parcurgerea arborilor de directoare cu un script
Dacă trebuie să traversați directoare în interiorul unui script, puteți utiliza comanda find
în interiorul scriptului. Dacă trebuie – sau doar doriți – să faceți singur căutările recursive, puteți face și asta.
#!/bin/bash shopt -s dotglob nullglob function recursive { local current_dir dir_or_file pentru curent_dir în $1; do echo "Comandă director pentru:" $current_dir pentru dir_or_file în „$current_dir”/*; do if [[ -d $dir_or_file ]]; apoi recursiv „$dir_or_file” altfel wc $dir_or_file fi Terminat Terminat } recursiv „$1”
Copiați textul într-un editor și salvați-l ca „recurse.sh”, apoi utilizați comanda chmod
pentru a-l face executabil.
chmod +x recurs.sh
Scriptul stabilește două opțiuni de shell, dotglob
și nullglob
.
Setarea dotglob
înseamnă nume de fișiere și directoare care încep cu un punct „ .
” va fi returnat atunci când termenii de căutare cu caractere wildcard sunt extinși. Acest lucru înseamnă efectiv că includem fișiere și directoare ascunse în rezultatele căutării noastre.
Setarea nullglob
înseamnă că modelele de căutare care nu găsesc niciun rezultat sunt tratate ca un șir gol sau nul. Ele nu folosesc implicit termenul de căutare în sine. Cu alte cuvinte, dacă căutăm totul dintr-un director folosind caracterul metalic asterisc „ *
”, dar nu există rezultate, vom primi un șir nul în loc de un șir care conține un asterisc. Acest lucru împiedică scriptul să încerce din neatenție să deschidă un director numit „*” sau să trateze „*” ca un nume de fișier.
Apoi, definește o funcție numită recursive
. Aici se întâmplă lucrurile interesante.
Sunt declarate două variabile, numite current_dir
și dir_or_file
. Acestea sunt variabile locale și pot fi referite numai în cadrul funcției.
O variabilă numită $1
este, de asemenea, utilizată în cadrul funcției. Acesta este primul (și singurul) parametru transmis funcției atunci când este apelată.
Scriptul folosește două bucle for
, una imbricată în cealaltă. Prima buclă for
(exterioară) este folosită pentru două lucruri.
Una este să rulați orice comandă pe care doriți să o efectuați în fiecare director. Tot ceea ce facem aici este să redăm numele directorului în fereastra terminalului. Desigur, puteți utiliza orice comandă sau secvență de comenzi sau puteți apela o altă funcție de script.
Al doilea lucru pe care îl face bucla for externă este să verifice toate obiectele sistemului de fișiere pe care le poate găsi - care vor fi fie fișiere, fie directoare. Acesta este scopul buclei for
interior. La rândul său, fiecare nume de fișier sau director este trecut în variabila dir_or_file
.
Variabila dir_or_file
este apoi testată într-o instrucțiune if pentru a vedea dacă este un director.
- Dacă este, funcția se autoapelează și transmite numele directorului ca parametru.
- Dacă variabila
dir_or_file
nu este un director, atunci trebuie să fie un fișier. Orice comandă pe care doriți să le aplicați fișierului poate fi apelată din clauzaelse
a instrucțiuniiif
. De asemenea, puteți apela o altă funcție în cadrul aceluiași script.
Linia finală din script apelează funcția recursive
și trece în primul parametru de linie de comandă $1
ca director de pornire în care să căutați. Acesta este ceea ce declanșează întregul proces.
Să rulăm scriptul.
./recurse.sh lucru
Directoarele sunt parcurse, iar punctul din script în care ar fi rulată o comandă în fiecare director este indicat de liniile „Comandă director pentru:”. Fișierele găsite au comanda wc
rulată pe ele pentru a număra liniile, cuvintele și caracterele.
Primul director procesat este „work”, urmat de fiecare ramură de director imbricată a arborelui.
Un punct interesant de remarcat este că puteți schimba ordinea în care sunt procesate directoarele, mutând comenzile specifice directorului de la a fi deasupra buclei for interioare la a fi sub aceasta.
Să mutăm linia „Directory command for:” după terminarea done
for
interne.
#!/bin/bash shopt -s dotglob nullglob function recursive { local current_dir dir_or_file pentru curent_dir în $1; do pentru dir_or_file în „$current_dir”/*; do if [[ -d $dir_or_file ]]; apoi recursiv „$dir_or_file” altfel wc $dir_or_file fi Terminat echo "Comandă director pentru:" $current_dir Terminat } recursiv „$1”
Acum vom rula scriptul încă o dată.
./recurse.sh lucru
De data aceasta, directoarele au comenzile aplicate mai întâi de la cele mai profunde niveluri, lucrând înapoi în sus ramurile arborelui. Directorul transmis ca parametru scriptului este procesat ultimul.
Dacă este important să aveți directoare mai profunde procesate mai întâi, așa puteți face acest lucru.
Recursiunea este ciudată
Este ca și cum te-ai suna pe propriul tău telefon și ți-ai lăsa un mesaj pe care să-l spui când te vei întâlni în mod repetat.
Poate fi nevoie de ceva efort înainte să-i înțelegi beneficiile, dar când o vei face, vei vedea că este o modalitate elegantă din punct de vedere programatic de a aborda problemele grele.
LEGATE: Ce este recursiunea în programare și cum o folosiți?