Jak przeszukiwać drzewo katalogów w systemie Linux?
Opublikowany: 2022-07-21
Katalogi w systemie Linux umożliwiają grupowanie plików w odrębne, oddzielne kolekcje. Minusem jest to, że przechodzenie z katalogu do katalogu w celu wykonania powtarzalnego zadania staje się żmudne. Oto jak to zautomatyzować.
Wszystko o katalogach
Pierwszym poleceniem, którego nauczysz się po zapoznaniu się z Linuksem, jest prawdopodobnie ls
, ale cd
nie zostanie daleko w tyle. Zrozumienie katalogów i sposobu poruszania się po nich, szczególnie zagnieżdżonych podkatalogów, jest fundamentalną częścią zrozumienia, jak Linux organizuje się i jak możesz organizować własną pracę w pliki, katalogi i podkatalogi.
Zrozumienie koncepcji drzewa katalogów — i sposobu poruszania się między nimi — jest jednym z wielu małych kamieni milowych, które mijasz, zaznajamiając się z krajobrazem Linuksa. Użycie cd
ze ścieżką prowadzi do tego katalogu. Skróty takie jak cd ~
lub cd
same zabierają cię z powrotem do twojego katalogu domowego, a cd ..
przenosi cię o jeden poziom wyżej w drzewie katalogów. Prosty.
Jednak nie ma równie prostego sposobu na uruchomienie polecenia we wszystkich katalogach drzewa katalogów. Istnieją różne sposoby na osiągnięcie tej funkcjonalności, ale nie ma standardowej komendy Linuksa przeznaczonej do tego celu.
Niektóre polecenia, takie jak ls
, mają opcje wiersza poleceń, które zmuszają je do działania rekurencyjnego , co oznacza, że zaczynają się w jednym katalogu i metodycznie przechodzą przez całe drzewo katalogów poniżej tego katalogu. Dla ls
jest to opcja -R
(rekurencyjna).
Jeśli potrzebujesz użyć polecenia, które nie obsługuje rekurencji, musisz samodzielnie udostępnić funkcję rekurencyjną. Oto jak to zrobić.
POWIĄZANE: 37 ważnych poleceń systemu Linux, które powinieneś znać
Drzewo Polecenie
Polecenie tree
nie pomoże nam w bieżącym zadaniu, ale ułatwia zobaczenie struktury drzewa katalogów. Rysuje drzewo w oknie terminala, dzięki czemu możemy uzyskać natychmiastowy przegląd katalogów i podkatalogów, które tworzą drzewo katalogów, oraz ich względne pozycje w drzewie.
Musisz zainstalować tree
.
W Ubuntu musisz wpisać:
drzewo instalacji sudo apt
W Fedorze użyj:
drzewo instalacji sudo dnf
Na Manjaro polecenie to:
sudo pacman -Sy drzewo
Użycie tree
bez parametrów rysuje drzewo poniżej bieżącego katalogu.
drzewo
Możesz podać ścieżkę do tree
w wierszu poleceń.
drzewo praca
Opcja -d
(katalogi) wyklucza pliki i pokazuje tylko katalogi.
drzewo -d praca
Jest to najwygodniejszy sposób uzyskania przejrzystego obrazu struktury drzewa katalogów. Przedstawione tutaj drzewo katalogów jest tym, które zostało użyte w poniższych przykładach. Istnieje pięć plików tekstowych i osiem katalogów.
Nie analizuj danych wyjściowych z ls do katalogów przechodzenia
Twoja pierwsza myśl może brzmieć, jeśli ls
może rekursywnie ls
drzewo katalogów, dlaczego nie użyć go właśnie do tego i przekazać dane wyjściowe do innych poleceń, które analizują katalogi i wykonują pewne działania?
Parsowanie wyjścia ls
jest uważane za złą praktykę. Ze względu na możliwość tworzenia w Linuksie nazw plików i katalogów zawierających różnego rodzaju dziwne znaki, bardzo trudno jest stworzyć ogólny, uniwersalnie poprawny parser.
Być może nigdy świadomie nie stworzysz nazwy katalogu tak niedorzecznej jak ta, ale może to być błąd w skrypcie lub aplikacji.
Analizowanie prawidłowych, ale słabo przemyślanych nazw plików i katalogów jest podatne na błędy. Istnieją inne metody, których możemy użyć, które są bezpieczniejsze i znacznie bardziej niezawodne niż poleganie na interpretacji wyniku ls
.
Korzystanie z polecenia Znajdź
Polecenie find
ma wbudowane funkcje rekurencyjne, a także ma możliwość uruchamiania poleceń za nas. To pozwala nam budować potężne one-linery. Jeśli jest to coś, czego prawdopodobnie będziesz chciał użyć w przyszłości, możesz zmienić swój jednowierszowy w alias lub funkcję powłoki.
To polecenie rekurencyjnie przegląda drzewo katalogów w poszukiwaniu katalogów. Za każdym razem, gdy znajdzie katalog, wypisuje nazwę katalogu i powtarza wyszukiwanie w tym katalogu. Po zakończeniu przeszukiwania jednego katalogu opuszcza ten katalog i wznawia wyszukiwanie w swoim katalogu nadrzędnym.
find work -type d -execdir echo "In:" {} \;
Możesz zobaczyć, w jakiej kolejności katalogi są wymienione, jak przebiega wyszukiwanie w drzewie. Porównując dane wyjściowe polecenia tree
z danymi wyjściowymi polecenia find
jednowierszowego, zobaczysz, jak find
przeszukuje kolejno każdy katalog i podkatalog, aż dotrze do katalogu bez podkatalogów. Następnie cofa się o jeden poziom i wznawia wyszukiwanie na tym poziomie.
Oto jak składa się polecenie.
- find : polecenie
find
. - work : katalog, w którym rozpocznie się wyszukiwanie. Może to być ścieżka.
- -type d : szukamy katalogów.
- -execdir : Zamierzamy wykonać polecenie w każdym znalezionym katalogu.
- echo „In:” {} : To jest polecenie. Po prostu wyświetlamy nazwę katalogu w oknie terminala. „{}” zawiera nazwę bieżącego katalogu.
- \; : To jest średnik używany do zakończenia polecenia. Musimy uciec przed nim za pomocą odwrotnego ukośnika, aby Bash nie zinterpretował go bezpośrednio.
Z niewielką zmianą możemy sprawić, że polecenie find zwróci pliki pasujące do wskazówki wyszukiwania. Musimy dołączyć opcję -name i wskazówkę wyszukiwania. W tym przykładzie szukamy plików tekstowych pasujących do „*.txt” i wyświetlamy ich nazwę w oknie terminala.

find work -name "*.txt" -type f -execdir echo "Znaleziono:" {} \;
To, czy szukasz plików, czy katalogów, zależy od tego, co chcesz osiągnąć. Aby uruchomić polecenie w każdym katalogu , użyj -type d
. Aby uruchomić polecenie na każdym zgodnym pliku , użyj -type f
.
To polecenie zlicza wiersze we wszystkich plikach tekstowych w katalogu początkowym i podkatalogach.
znajdź pracę -nazwa "*.txt" -type f -execdir wc -l {} \;
POWIĄZANE: Jak korzystać z polecenia find w systemie Linux
Przechodzenie przez drzewa katalogów za pomocą skryptu
Jeśli potrzebujesz przeszukiwać katalogi wewnątrz skryptu, możesz użyć polecenia find
wewnątrz skryptu. Jeśli musisz – lub po prostu chcesz – wykonać wyszukiwania rekurencyjne samodzielnie, możesz to zrobić.
#!/kosz/bash shopt -s dotglob nullglob funkcja rekurencyjna { lokalny bieżący_katalog katalog_lub_plik dla current_dir w $1; robić echo "Polecenie katalogu dla:" $current_dir dla katalogu_lub_pliku w "$bieżący_katalog"/*; robić if [[ -d $katalog_lub_plik ]]; następnie rekurencyjne "$katalog_lub_plik" w przeciwnym razie wc $katalog_lub_plik fi Gotowe Gotowe } rekurencyjne "$1"
Skopiuj tekst do edytora i zapisz go jako „recurse.sh”, a następnie użyj polecenia chmod
, aby uczynić go wykonywalnym.
chmod +x recurse.sh
Skrypt ustawia dwie opcje powłoki, dotglob
i nullglob
.
Ustawienie dotglob
oznacza nazwy plików i katalogów, które zaczynają się od kropki „ .
” zostanie zwrócony po rozwinięciu wyszukiwanych haseł z symbolami wieloznacznymi. Oznacza to, że w naszych wynikach wyszukiwania uwzględniamy ukryte pliki i katalogi.
Ustawienie nullglob
oznacza, że wzorce wyszukiwania, które nie znajdują żadnych wyników, są traktowane jako ciąg pusty lub pusty. Nie są one domyślnie używane do samego wyszukiwanego hasła. Innymi słowy, jeśli szukamy wszystkiego w katalogu, używając symbolu wieloznacznego gwiazdki „ *
”, ale nie ma wyników, zamiast ciągu zawierającego gwiazdkę otrzymamy ciąg pusty. Zapobiega to przypadkowemu otwarciu przez skrypt katalogu o nazwie „*” lub potraktowaniu „*” jako nazwy pliku.
Następnie definiuje funkcję o nazwie recursive
. Tutaj dzieją się ciekawe rzeczy.
Deklarowane są dwie zmienne o nazwach current_dir
i dir_or_file
. Są to zmienne lokalne i można się do nich odwoływać tylko w ramach funkcji.
W funkcji używana jest również zmienna o nazwie $1
. Jest to pierwszy (i jedyny) parametr przekazywany do funkcji podczas jej wywołania.
Skrypt używa dwóch pętli for
, jednej zagnieżdżonej w drugiej. Pierwsza (zewnętrzna) pętla for
służy do dwóch rzeczy.
Jednym z nich jest uruchomienie dowolnego polecenia, które chcesz wykonać w każdym katalogu. Wszystko, co tutaj robimy, to powtarzanie nazwy katalogu w oknie terminala. Możesz oczywiście użyć dowolnego polecenia lub sekwencji poleceń lub wywołać inną funkcję skryptu.
Drugą rzeczą, jaką robi zewnętrzna pętla for, jest sprawdzenie wszystkich znalezionych obiektów systemu plików — którymi będą pliki lub katalogi. Taki jest cel wewnętrznej pętli for
. Z kolei każda nazwa pliku lub katalogu jest przekazywana do zmiennej dir_or_file
.
Zmienna dir_or_file
jest następnie testowana w instrukcji if w celu sprawdzenia, czy jest to katalog.
- Jeśli tak, funkcja wywołuje samą siebie i przekazuje nazwę katalogu jako parametr.
- Jeśli zmienna
dir_or_file
nie jest katalogiem, to musi być plikiem. Wszelkie polecenia, które chcesz zastosować do pliku, można wywołać z klauzulielse
instrukcjiif
. Możesz również wywołać inną funkcję w tym samym skrypcie.
Ostatnia linia w skrypcie wywołuje funkcję recursive
i przekazuje pierwszy parametr wiersza poleceń $1
jako katalog początkowy do przeszukania. To właśnie rozpoczyna cały proces.
Uruchommy skrypt.
./recurse.sh praca
Katalogi są przeszukiwane, a punkt w skrypcie, w którym polecenie zostanie uruchomione w każdym katalogu, jest wskazywany przez wiersze „Polecenie katalogu dla:”. Znalezione pliki mają uruchamiane na nich polecenie wc
, aby policzyć wiersze, słowa i znaki.
Pierwszym przetwarzanym katalogiem jest „praca”, po którym następuje każda zagnieżdżona gałąź katalogu drzewa.
Warto zauważyć, że możesz zmienić kolejność przetwarzania katalogów, przenosząc polecenia specyficzne dla katalogu z pozycji powyżej wewnętrznej pętli for na znajdującą się pod nią.
Przenieśmy wiersz „Polecenie do katalogu dla:” za done
wewnętrznej pętli for
.
#!/kosz/bash shopt -s dotglob nullglob funkcja rekurencyjna { lokalny bieżący_katalog katalog_lub_plik dla current_dir w $1; robić dla katalogu_lub_pliku w "$bieżący_katalog"/*; robić if [[ -d $katalog_lub_plik ]]; następnie rekurencyjne "$katalog_lub_plik" w przeciwnym razie wc $katalog_lub_plik fi Gotowe echo "Polecenie katalogu dla:" $current_dir Gotowe } rekurencyjne "$1"
Teraz ponownie uruchomimy skrypt.
./recurse.sh praca
Tym razem do katalogów stosuje się najpierw polecenia z najgłębszych poziomów, pracując w kopii zapasowej gałęzi drzewa. Katalog przekazany jako parametr do skryptu jest przetwarzany jako ostatni.
Jeśli ważne jest, aby najpierw przetworzyć głębsze katalogi, tak możesz to zrobić.
Rekurencja jest dziwna
To tak, jakby dzwonić do siebie na własny telefon i zostawiać sobie wiadomość, aby powiedzieć sobie, kiedy następnym razem się spotkasz — wielokrotnie.
Może zająć trochę wysiłku, zanim zrozumiesz jego zalety, ale gdy to zrobisz, zobaczysz, że jest to programowo elegancki sposób rozwiązywania trudnych problemów.
POWIĄZANE: Co to jest rekurencja w programowaniu i jak z niej korzystać?