Polecenia które pełnią rolę filtrów są często używane w mechanizmie potoków, który poznaliśmy w podrozdziale poprzednim. Odpowiednie użycie filtrów w połączeniu z potokiem (ewentualnie jego rozgałęzieniem wywoływanym przez polecenie tee ) umożliwia użytkownikowi wykonanie większości codziennych prac administratora systemu bez potrzeby pisania dodatkowych programów.

Poznanie struktury poleceń zbudowanych z filtrów i potoków jest niezbędne do dobrego opanowania systemu operacyjnego Linux.

Przypomnijmy, że potok jest ciągiem poleceń prostych lub złożonych, które są odseparowane od siebie przez znak  | . Rezultat każdego polecenia – z wyjątkiem ostatniego – jest traktowane przez polecenie następne jako jego standardowe wejście. Innymi słowy - potok – jest mechanizmem komunikacji pomiędzy różnymi poleceniami, który im pozwala wymieniać między sobą dane i używając w nim filtrów możemy wykonywać prawie wszystkie operacje na plikach.

Jest charakterystyczne, że niektóre polecenia są dopasowywane do  współpracy między sobą. I tak polecenie sort współpracuje zawsze lub prawie zawsze z poleceniem uniq. Należy podkreślić, że polecenie sort jest także dopasowane do współpracy z poleceniami  grep   cut   i  paste. Jest chyba dla każdego oczywiste, że bardziej wydajne jest umieszczenie w mechanizmie potoku polecenia sort po poleceniu  grep lub cut, które szukają danych, z tego prostego powodu, że wtedy sortujemy tylko część wyselekcjonowanego pliku.

Jest to jeden z wielu przykładów. Niewątpliwie dopasowane do współpracy są także polecenia cut  paste i join. Polecenie cut wycina z pliku pola które można połączyć używając polecenia  paste lub join. Przypomnijmy raz jeszcze wygląd mechanizmu potoku, jak wiemy operator | łączy standardowe wyjście polecenia1 ze standardowym wyjściem polecenia2.

polecenie1    |    polecenie2

 

Potok może być dłuższy i zawierać więcej niż dwa polecenia:

polecenie1  |  polecenie2   |   polecenie 3  |  polecenie4   | polecenie5

 

W takim przypadku polecenia środkowe (polecenie2,3,4) muszą być filtrami. Jak widzimy struktura mechanizmu potoku dostosowana jest do zasad funkcjonowania filtrów. Często stosując  filtry i potoki stosujemy także przekierowania, które polega na tym, że standardowe wejścia-wyjścia mogą być skierowane do pliku, Skierowanie standardowego wyjścia polega na wysłaniu tekstu wyświetlanego na ekranie do pliku.

Wszystkie standardowe wejścia-wyjścia  każdego procesu można także skierować do odpowiednich plików i proces zamiast szukać informacji w sygnałach wysyłanych z klawiatury, będzie ich poszukiwał w odpowiednich plikach. Tak więc rezultat potoku złożonych z wielu poleceń skierowujemy do pliku. Mechanizm ten przy niektórych poleceniach jest konieczny. Przetestujmy teraz mechanizm potoków których poleceniami są filtry (ale nie tylko).

Użytkownik chciałby się dowiedzieć ile plików w katalogu /dev zaczyna się od literhd ? Ćwiczenie jest względnie proste pod warunkiem, że użytkownik wie gdzie w strukturze drzewa katalogowego znajduje się katalog  /dev :

$  ls  /dev/hd*  |  wc -l

 

Użytkownik chciałby się dowiedzieć jaki plik w jego repertuarze jest największy – jakie polecenia wykorzystać  ? Przede wszystkim pierwszym poleceniem potoku będzie dobrze wam znane  polecenie  ls  -l

$  ls –l  |   sort  -n   +4   |     tail 1

 

Użytkownik często – szczególnie na koniec dnia pracy – chciałby wiedzieć jakie pliki tego dnia zostały zmodyfikowane. Załóżmy, że jest 10 lipca, w takim razie potok, który wyświetli tą informacje będzie wyglądał następujący:

$ ls  -l  |   grep  -n   ‘Jul  10’

 

Już po tych trzech przykładach widzimy, że użytkownik musi znać struktury wyświetleń podstawowych poleceń Linuxa. Niewątpliwie najważniejszym poleceniem jest – wielokrotnie w kursie omawiane – polecenie  ls. Stąd kładziemy nacisk na poznanie jego struktury.

Użytkownik chciałby wyświetlić na ekranie tylko informacje o tych którzy zapisują pliki w katalogu. W takim przypadku wydajemy polecenie, które jest potokiem:

ls –l  |   cut  d” ”   -f5

 

Aby to wykonać użytkownik musi wiedzieć, że pierwsze pole (informacji uzyskanej dzięki poleceniu  ls  -l) definiuje uprawnienia użytkownika, a czwarte liczbę linków.

 

Czy wiesz co wyświetli się na ekranie po wpisaniu następującego polecenia ?

$  ls  -l  |   grep  ”rwxr-xr-x”  |  more

 

Wydajność mechanizmu potoku, możemy docenić jeżeli np. będziemy chcieli policzyć liczbę użytkowników systemu którzy używają bash-shell

$  cat  /etc/passwd  |  grep  /bin/bash   |  wc –l

 

Polecenie  cat wyświetla zawartość pliku  /etc/passwd w którym zawarty jest opis wszystkich użytkowników. Filtr  grep selekcjonuje wiersze w których znajduje się ciąg znaków  /bin/bash. Filtr  wc liczy liczbę wierszy wyselekcjonowanych przez filtr  grep.

 

Częstym błędem – używając mechanizmu potoków i filtrów – jest nielogiczne umieszczenie w potoku poszczególnych poleceń. Załóżmy, że chcielibyśmy z pliku  passwd wyselekcjonować użytkowników których katalogi domowe znajdują się w systemie plików linux1. Możemy dokonać tego najpierw sortując plik passwd, nastepnie wyszukania szukanej informacji a na koniec jej wycięcia:

$   sort  -t:   +0  -1 /etc/passwd  |   grep linux1  |  cut  -f1  -d:

 

Zauważmy, jednak, że w tym przypadku zmuszamy shell do sortowania całego pliku  passwd i dopiero następnie wybierania szukanej informacji. Bardziej wydajnie – dlaczego ?  - byłoby najpierw wybrać dane i dopiero potem je posortować.

$  grep  linux1   /etc/passwd  |  cut  -f1  -d:  |  sort

 

Ktoś może zauważyć, że różnica jest nieistotna bo i tak w efekcie uzyskujemy to co chcieliśmy. Jednak  trzeba wziąć pod uwagę, że plik passwd liczy niewiele wierszy i w takim wypadku, jego sortowanie odbędzie się błyskawicznie. Co jednak się stanie, jeżeli przy identycznym problemie, plik będzie liczył setki tysięcy wierszy ? Sortowanie będzie musiało zarezerwować dużą ilość pamięci i czas jego wykonywania będzie trwał nie kilka minut lecz nawet godzinę lub więcej, utrudniając prace i spowalniając egzekucje innych programów.

 

Zakończmy ten rozdział przykładem ilustrującym potęgę i prostotę mechanizmu potoków w połączeniu z filtrami. Załóżmy, że chcemy z tekstu zawartego w pliku plik3 utworzyć słownik alfabetyczny wszystkich słów z których składa się tekst. Problem możemy rozwiązać dzieląc go na trzy etapy:

1. tr         -     dzieli tekst na słowa

2. sort     -     sortuje słowa w porządku alfabetycznym

3. uniq     -     znosi powtarzające się słowa


$  tr  -cs   ‘a-zA-Z‘  ‘\12’  < plik3  |  sort   |  uniq   >  plk4

 

W przykładzie tym wykorzystaliśmy mechanizm potoków, przekierowań używając trzech filtrów   tr   sort  uniq do rozwiązania dość skomplikowanego zadania.

 


Kurs Linux - Bash użycie filtrów