Polecenie WC,Sort,Tr,Grep,Egrep,Find.

 

Polecenie SORT

Sortowanie jest jednym z ważniejszych elementów programowania. Znajomość różnych algorytmów i technik sortowania to ważna część wiedzy programisty.

Tutaj jednak zajmiemy się czymś znacznie prostszym: wykorzystaniem unixowego polecenia sort do porządkowania jednego lub więcej plików, wiersz po wierszu, wedle ustalonych przez nas reguł. A przy okazji rozejrzymy się po środowisku w jakim pracujemy.

Wielu użytkowników kończy swoją znajomość polecenia sort na poleceniach typu:

 

sort some_file.txt
 

Domyślne zachowanie tego polecenia dla wielu prostych zastosowań będzie wystarczające - wyświetli w terminalu posortowane wiersze wskazanego pliku. Przyjrzymy się jednak działaniu tego polecenia nieco dokładniej. Można oczywiście przestudiować manual (polecenie man sort) ale łatwiej jest poznać specyfikę niektórych opcji i możliwości na przykładach.

Stwórzmy (polecenie touch) plik literki.txt zawierający po jednej literze w wierszu. Polecenie cat pozwoli nam wyświetlić jego zawartość (w tym i pozostałych przykładach znak dolara ($) zastępuje całe zgłoszenie systemowe (ang.: Prompt):

 

cat literki.txt
b
D
c
A
C
B
d
a
 

Podstawowe użycie polecenia sort widzimy poniżej:

 

sort literki.txt
a
A
b
B
c
C
d
D
 

a gdybyśmy chcieli posortować w odwrotnej kolejności:

 

sort -r letters.txt
D
d
C
c
B
b
A
a
 

W zasadzie wszystko dobrze, ale trochę dziwnie zachowuje się kolejność małych i dużych liter. W manualu do polecenia sort czytamy, że opcja: -f (lub --ignore-case) powoduje nierozróżnianie małych i dużych liter przy porównywaniu. Powinno to być zachowanie domyślne, ale sprawdźmy:

 
sort -f literki.txt
a
A
b
B
c
C
d
D

sort -rf literki.txt
D
d
C
c
B
b
A
a

Oszustwo! Widać gołym okiem, że nierozróżnianie małych i dużych liter nie jest prawdą. Co gorsza polecenie sort zachowuje się niestabilnie, to znaczy zmienia kolejność wierszy również tam, gdzie powinno traktować je jako "równe" z punktu widzenia reguł sortowania. Dopiero dodanie opcji -s (--stable) zmienia sytuację:

 

sort -rfs literki.txt
D
d
c
C
b
B
A
a

sort -fs literki.txt
A
a
b
B
c
C
D
d

Dlaczego tak jest? Ano, po szczegółowej lekturze opisu działania polecenia sort można się dowiedzieć, że jeśli sortowane wiersze nie różnią się z punktu widzenia przyjętych reguł to jako ostateczne kryterium stosowane jest jeszcze porównywanie kodów znaków! Dopiero opcja -s wyłącza to ostatnie porównywanie.

Zmodyfikujmy plik literki.txt, tak by otrzymać:

 

cat literki.txt
b
D
c
ą
A
C
B
d
ć
a
 

Kody "polskich literek" 'ą' oraz 'ć' powinny umieszczać je daleko od 'a' czy 'c' . Sprawdźmy:

 

sort -f literki.txt
a
A
ą
b
B
c
C
ć
d
D

sort -fs literki.txt
A
a
ą
b
B
c
C
ć
D
d
 

Nadal coś nie tak! Duże i małe litery reagują na opcję -s (to znaczy duże i małe te same litery występuja teraz w takiej samej kolejności jak w pliku nieposortowanym) ale system skądś wie, że 'ą' jest w polskim alfabecie przed 'b' i kody najwyraźniej nie mają tu nic do rzeczy.

Jak przeczytamy manual polecenia sort do samego końca to znajdziemy jeszcze ostrzeżenie:

 
*** WARNING *** The locale specified by the environment affects sort
order. Set LC_ALL=C to get the traditional sort order that uses native
byte values.

Cóż to oznacza? Sprawdźmy ustawienia językowe:

 

$ locale
LANG=pl_PL
LC_CTYPE="pl_PL"
LC_NUMERIC="pl_PL"
LC_TIME="pl_PL"
LC_COLLATE="pl_PL"
LC_MONETARY="pl_PL"
LC_MESSAGES="pl_PL"
LC_PAPER="pl_PL"
LC_NAME="pl_PL"
LC_ADDRESS="pl_PL"
LC_TELEPHONE="pl_PL"
LC_MEASUREMENT="pl_PL"
LC_IDENTIFICATION="pl_PL"
LC_ALL=pl_PL
 

Widać, że system wie, iż posługujemy się językiem polskim i stąd jego "nadinteligencja" przy sortowaniu. Ale rada zawarta w powyższym ostrzeżeniu nie jest najlepsza - ustawienieLC_ALL="C" spowoduje przestawienie całego naszego środowiska na język angielski i siedmiobitowy kod ASCII. Polecenie man locale wyjaśnia, do czego służą poszczególne zmienne oraz, ze ustawienie zmiennej LC_ALL ma najwyższy priorytet. O kolejności sortowania decyduje ustawienie zmiennej LC_COLLATE. Aby jednak zadziałała musimy usunąć ustawienie zmiennej LC_ALL. Spróbujmy:

 

LC_ALL=

$ locale
LANG=pl_PL
LC_CTYPE="pl_PL"
LC_NUMERIC="pl_PL"
LC_TIME="pl_PL"
LC_COLLATE="pl_PL"
LC_MONETARY="pl_PL"
LC_MESSAGES="pl_PL"
LC_PAPER="pl_PL"
LC_NAME="pl_PL"
LC_ADDRESS="pl_PL"
LC_TELEPHONE="pl_PL"
LC_MEASUREMENT="pl_PL"
LC_IDENTIFICATION="pl_PL"
LC_ALL=                       <---------------------

export LC_COLLATE=C

$ locale
LANG=pl_PL
LC_CTYPE="pl_PL"
LC_NUMERIC="pl_PL"
LC_TIME="pl_PL"
LC_COLLATE=C                  <----------------------
LC_MONETARY="pl_PL"
LC_MESSAGES="pl_PL"
LC_PAPER="pl_PL"
LC_NAME="pl_PL"
LC_ADDRESS="pl_PL"
LC_TELEPHONE="pl_PL"
LC_MEASUREMENT="pl_PL"
LC_IDENTIFICATION="pl_PL"
LC_ALL=

sort literki.txt
A
B
C
D
a
b
c
d
ą
ć

sort -f literki.txt
A
a
B
b
C
c
D
d
ą
ć
 

Uff. Umiemy sortować litery. A co z liczbami? Stwórzmy plik numerki.txt:

 

cat numerki.txt
5
4
12
1
3
56
 

i spróbujmy posortować jego wiersze:

 

sort numerki.txt
1
12
3
4
5
56
 

Wiersze nie są uporządkowane numerycznie ale łatwo zgadnąć co się stało: polecenie sort nic nie wie o naszych zamiarach i nadal sortuje według kolejności leksykograficznej. Czyli najpierw według pierwszego znaku, potem drugiego (jeśli jest) itd. lekarstwem jest opcja -n:

 

sort -n numerki.txt
1
3
4
5
12
56
 

Działa! Ale zmodyfikujmy plik numerki.txt następująco:

 

cat numerki.txt
+5
-4
+0.12
-0.1
+0.3
-0.56
 

Wynik sortowania będzie zaskakujący:

 

sort -n numerki.txt
-4
+0.12
+0.3
+5
-0.1
-0.56
 

Jeśli ktoś sądzi, że użycie opcji -g zamiast -n pomoże (a tak sugeruje dokumentacja) to jest w błędzie:

 

sort -g numerki.txt
-4
+0.12
+0.3
-0.1
-0.56
+5

Jest jeszcze dziwniej!. Powodem znowu są ustawienia językowe! Przypomnijmy je sobie:

 

$ locale
LANG=pl_PL
LC_CTYPE="pl_PL"
LC_NUMERIC="pl_PL"
LC_TIME="pl_PL"
LC_COLLATE=C
LC_MONETARY="pl_PL"
LC_MESSAGES="pl_PL"
LC_PAPER="pl_PL"
LC_NAME="pl_PL"
LC_ADDRESS="pl_PL"
LC_TELEPHONE="pl_PL"
LC_MEASUREMENT="pl_PL"
LC_IDENTIFICATION="pl_PL"
LC_ALL=

Teraz wszystko psuje ustawienie: LC_NUMERIC="pl_PL". Czemu?!?!? Bo w języku polskim separatorem części dziesiętnej jest... przecinek. Polecenie sort posłusznie sortuje według kolejności liczbowej, pomijając te części wierszy, które nie są liczbami (czyli od kropki w prawo!). Tak więc najpierw mamy -4, potem cztery razy zero a potem +5. Dopiero zmiana naLC_NUMERIC=C daje oczekiwany wynik:

 

export LC_NUMERIC=C

sort -g numerki.txt
-4
-0.56
-0.1
+0.12
+0.3
+5
 
 

Sortowanie nieco bardziej zaawansowane

Wyprodukujmy plik tablica.txt (proponuje skopiować zawartość z przeglądarki zamiast wklepywania zawartości)), który wygląda tak:

 

cat tablica.txt
| 23 | 12 | 32 | 93 | 75 |
| 43 | 17 | 52 | 91 | 22 |
| 77 | 73 | 14 | 48 | 37 |
| 44 | 51 | 52 | 36 | 54 |
| 41 | 25 | 43 | 26 | 99 |
| 17 | 21 | 46 | 31 | 24 |
| 28 | 83 | 85 | 42 | 27 |
| 23 | 14 | 37 | 13 | 75 |
 

Dokumentacja polecenia sort mówi, że wiersze pliku wejściowego można sortować według poszczególnych pół lub grup pól. Służy do tego opcja: -k POS1[,POS2], gdzie POS1 to numer pierwszego pola branego pod uwagę a opcjonalny parametr POS2 to numer ostatniego pola. Zobaczmy jak to działa:

 

sort -n -k 4 tablica.txt
| 23 | 12 | 32 | 93 | 75 |
| 23 | 14 | 37 | 13 | 75 |
| 43 | 17 | 52 | 91 | 22 |
| 17 | 21 | 46 | 31 | 24 |
| 41 | 25 | 43 | 26 | 99 |
| 44 | 51 | 52 | 36 | 54 |
| 77 | 73 | 14 | 48 | 37 |
| 28 | 83 | 85 | 42 | 27 |
 

Cóż, wiersze są posortowane, ale według drugiej kolumny a nie czwartej! Czemu? Ano komputer to nie wróżka, i niby skąd ma wiedzieć co uważamy za "pole" w wierszu? Domyślnym separatorem pól są odstępy! To wyjaśnia powyższy wynik sortowania. Zaradzić temu można przy pomocy opcji -t (--field-separator=SEPARATOR) po której podajemy jaki znak ma być uważany za separator pól. Zatem polecenie:

 

sort -n -t'|' -k 4 tablica.txt
| 77 | 73 | 14 | 48 | 37 |
| 23 | 12 | 32 | 93 | 75 |
| 23 | 14 | 37 | 13 | 75 |
| 41 | 25 | 43 | 26 | 99 |
| 17 | 21 | 46 | 31 | 24 |
| 43 | 17 | 52 | 91 | 22 |
| 44 | 51 | 52 | 36 | 54 |
| 28 | 83 | 85 | 42 | 27 |
 

powinno posortować plik według czwartej kolumny. Jak widać posortowało według trzeciej! Dlaczego? Ano dlatego, że każdy wiersz zaczyna się od znaku zdefiniowanego jako separator, tak więc komputer "widzi" przed nim "puste pole" numer 1. Aby posortować według czwartej kolumny musimy w takim przypadku wydać polecenie:

 

sort -n  -t'|' -k 5 tablica.txt
| 23 | 14 | 37 | 13 | 75 |
| 41 | 25 | 43 | 26 | 99 |
| 17 | 21 | 46 | 31 | 24 |
| 44 | 51 | 52 | 36 | 54 |
| 28 | 83 | 85 | 42 | 27 |
| 77 | 73 | 14 | 48 | 37 |
| 43 | 17 | 52 | 91 | 22 |
| 23 | 12 | 32 | 93 | 75 |
 
 

Poćwiczmy teraz nieco...

Polecenie $ ls -dla /etc/s* listuje wszystkie pliki i katalogi zawarte w /etc, których nazwy zaczynają się na literę 's' (na każdym komputerze wynik może się nieco różnić):

 

ls -dla /etc/s*
drwxr-xr-x 3 root root    4096 paź  1 12:58 /etc/sane.d
-rw-r--r-- 1 root root     666 sie 25  2009 /etc/scsi_id.config
-rw-r--r-- 1 root root    1287 lis 22  2008 /etc/securetty
drwxr-xr-x 2 root root    4096 paź  1 12:58 /etc/security
-rw-r--r-- 1 root root   71449 sie  2  2008 /etc/sensors3.conf
-rw-r--r-- 1 root root   85602 lip  3  2008 /etc/sensors.conf
-rw-r--r-- 1 root root    2950 cze 29  2001 /etc/serial.conf
-rw-r--r-- 1 root root   18480 sie 28  2008 /etc/services
drwxr-xr-x 3 root root    4096 paź  1 12:58 /etc/sgml
-rw-r----- 1 root shadow   854 lut 24  2010 /etc/shadow
-rw------- 1 root root     854 gru  2  2009 /etc/shadow-
-rw-r--r-- 1 root root     155 mar  3  2010 /etc/shells
drwxr-xr-x 2 root root    4096 paź  1 12:58 /etc/skel
drwxr-xr-x 3 root root    4096 paź  1 12:58 /etc/sound
drwxr-xr-x 2 root root    4096 paź  1 12:58 /etc/ssh
drwxr-xr-x 4 root root    4096 paź  1 12:58 /etc/ssl
drwxr-xr-x 2 root root    4096 paź  1 12:57 /etc/ssmtp
-r--r----- 1 root root     481 gru  1  2009 /etc/sudoers
-rw-r--r-- 1 root root    2275 sty 11  2009 /etc/sysctl.conf
drwxr-xr-x 2 root root    4096 sty 11  2009 /etc/sysctl.d
 

Polecenie ls domyślnie sortuje wiersze alfabetycznie według nazw. Gdybyśmy chcieli posortować wynik tego polecenia według liczby dowiązań do danego pliku lub katalogu (liczba całkowita po opisie uprawnień) to zrobilibyśmy to np. tak:

 

ls  -dla /etc/s* | sort -k2
-rw-r--r-- 1 root root   18480 sie 28  2008 /etc/services
-rw-r--r-- 1 root root   71449 sie  2  2008 /etc/sensors3.conf
-rw-r--r-- 1 root root   85602 lip  3  2008 /etc/sensors.conf
-rw-r--r-- 1 root root    1287 lis 22  2008 /etc/securetty
-rw-r--r-- 1 root root    2275 sty 11  2009 /etc/sysctl.conf
-rw-r--r-- 1 root root    2950 cze 29  2001 /etc/serial.conf
-rw-r--r-- 1 root root     155 mar  3  2010 /etc/shells
-r--r----- 1 root root     481 gru  1  2009 /etc/sudoers
-rw-r--r-- 1 root root     666 sie 25  2009 /etc/scsi_id.config
-rw------- 1 root root     854 gru  2  2009 /etc/shadow-
-rw-r----- 1 root shadow   854 lut 24  2010 /etc/shadow
drwxr-xr-x 2 root root    4096 paź  1 12:57 /etc/ssmtp
drwxr-xr-x 2 root root    4096 paź  1 12:58 /etc/security
drwxr-xr-x 2 root root    4096 paź  1 12:58 /etc/skel
drwxr-xr-x 2 root root    4096 paź  1 12:58 /etc/ssh
drwxr-xr-x 2 root root    4096 sty 11  2009 /etc/sysctl.d
drwxr-xr-x 3 root root    4096 paź  1 12:58 /etc/sane.d
drwxr-xr-x 3 root root    4096 paź  1 12:58 /etc/sgml
drwxr-xr-x 3 root root    4096 paź  1 12:58 /etc/sound
drwxr-xr-x 4 root root    4096 paź  1 12:58 /etc/ssl
 

Wykorzystaliśmy tu dodatkowo mechanizm "potokowania": pionowa kreska po pierwszym poleceniu (ls) powoduje przekazanie jego wyjścia jako wejścia do drugiego polecenia (sort). To z tego powodu w definicji separatora przy sortowaniu tablicy pionową kreskę ujęliśmy w apostrofy!

 

wc - Drukowanie informacji o zawartości pliku

Za pomocą polecenia wc można dowiedzieć się (nie otwierając pliku w żadnym edytorze tekstowym) informacji na temat ilości bajtów, słów, znaków, linii, oraz rozmiarze najdłuższej linii. Postać polecenia wygląda następująco.

$ wc [OPCJE] [plik(i)]

Podstawowe użycie tego polecenia drukuje w następującej kolejności: ilość wierszy, ilość słów, ilość bajtów i nazwę pliku. Rysunek 1 ilustruje to.

Polecenie wc
Rys 1. Polecenie wc - Wyświetlanie informacji o pliku


 

Jeśli wpiszemy większą ilość plików, to każdy z osobna zostanie obsłużony, a na koniec zostanie wyświelona łączna ilość poszczególnych elementów (rysunek 2). Jeśli nie wpiszemy nazwy pliku, to program będzie czytał dane ze standardowego wejścia, a po zakończeniu wpisywania (CTRL-D) informacje zostaną wyświetlone.

Polecenie wc
Rys 2. Polecenie wc - Wyświetlanie informacji o plikach


 

Istnieje możliwość wyświetlania wybranych elementów osobno. Jeśli chcemy wyświetlić tylko ilość bajtów, to używamy opcji -c, jeśli interesuje nas ilość znaków to opcja -mprzychodzi z pomocą. Ilość wierszy sprawdzamy za pomocą -l. Długość najdłuższego wiersza uzyskamy za pomocą -L. Ilość wierszy to opcja -w. Wszystkie wspomniane opcje zostały pokazane na rysunku 3.

Polecenie wc
 
 

tr - Przetłumacz, albo usuń znaki

Polecenie tr umożliwia zmianę znaków na inne, usuwanie nadmiernej ilości znaków (np. spacji, kropek, itp.). Ogólna składnia polecenia ma się następująco:

$ tr [OPCJE] SET1 [SET2]

Gdzie jako SET1 i SET2 rozumiemy znaki, które mają być wzorcami do zamiany. Jeśli narazie nie jest to jasne, nie ma co się przejmować, poniżej zostanie to wyjaśnione wraz z przykładami zastosowania polecenia tr.

Polecenie tr
Rys 1. Polecenie tr - Zmiana z małych na duże litery.


Jak widać na rysunku 1, podajemy nazwę polecenia - tr beż żadnych opcji, jako SET1 wpisujemy 'a-z', a jako SET2 'A-Z'. W ogólnej składni polecenia tr SET2 zosało napisane w nawiasach kwadratowych, a to dlatego, że nie jest wymagane przy niektórych opcjach polecenia tr (o tym za chwilę). 
Jak to działa? A więc wpisujemy polecenie tak jak widoczne jest na rysunku 1. Terminal będzie czekał, aż wpiszemy tekst i wciśniemy enter. Po wciśnięciu klawisza enter, polecenie wykonuje swoją rolę. W tym przypadku tłumaczy (zamienia) wszystki pobrane znaki zawarte w przedziale 'a-z' na znaki zawarte w przedziale A-Z, czyli krótko mówiąc zmienia wielkość liter, z małych na duże. 
W tym miejscu trzeba wspomnieć, że zakres znaków, które podajemy musi być odpowiedni, tzn. 'a-z' jest poprawnym zakresem, natomiast 'z-a' nie jest poprawnym zakresem i terminal wyświetli błąd:

tr: range-endpoints of `Z-A' are in reverse collating sequence order

Aby usunąć niektóre znaki, musimy je zdefiniować w SET1. W tym miejscu nie trzeba, a właściwie nie można ustawiać SET2, lecz trzeba ustawić opcję -d, która jest odpowiedzialna za znaki. Rysunek 2 pokazuje w jaki sposób można usunąć wszystkie kropki.

Polecenie tr
Rys 2. Polecenie tr - Usuwanie wszystkich kropek.


Opcja -s pozwala na usunięcie nadmiarowej ilości znaków ustawionych w SET1 i pozostawienie tylko jednego. Rysunek 3 pokazuje składnie i efekt działania tego polecenia.

Polecenie tr
Rys 3. Polecenie tr - Usuwanie nadmiarowej ilości kropek.
 
 
 

Polecenie Grep z wyrażeniami regularnymi

 

Polecenie  grep (globally look for a regular expression end print – co na polski można przetłumaczyć: wyszukaj w pliku napisów spełniających wyrażenie regularne i wyświetl je) służy do znalezienia każdego wystąpienia słowa – ciągu znaków, frazy – w pliku utworzonym w systemie Linux. Ogólny wzór polecenia  grep można przedstawić następująco:

grep  [ opcja ]   [ -e ]  [ wzór ]    [nazwa pliku]

 

Opcje

-b → wyświetla odnalezione miejsca

-c → wyświetla liczbę odnalezionych wyrażeń

-h  nie wypisuje nazwy plików przed każdym odnalezionym miejscem

-i  ignoruje różnice w wielkości liter

-l → wyświetla tylko nazwy plików w których odnaleziony został wzór

-n → wyświetla numer każdego wiersza, w którym został odnaleziony wzór

-s → brak wyświetlania jakichkolwiek komunikatów

-v → wyświetla tylko te wiersze, które nie zawierają wzoru

-w → wyświetla tylko te wiersz, w których wzór jest całym wyrazem

 

Kilka przykładów z poleceniem grep

$ grep   -n ‘^piotr:’  /etc/passwd

Wyjaśnienie: polecenie grep wyświetla na ekranie wiersz z pliku /etc/passwd który definiuje użytkownika „piotr” i dodatkowo poprzedza wiersz jego numerem w pliku /etc/passwd

 

$ ls  /   |   grep  „^r.*”

Wyjaśnienie:

 

$  ls  /   grep  „r.*”

 

Do nauki polecenia grep, które używane jest z wyrażeniami regularnymi musimy utworzyć plik pozwalający zaprezentować wszystkie możliwości zarówno polecenia grep jak i wyrażeń regularnych. Dane zawarte w tym pliku mogą wydawać się sztuczne lecz umożliwią nam one z względnie wystarczającym zapoznaniem się z omawianym tematem. Przy pomocy edytora vi (patrz rozdział IX) utwórzmy plik o nazwie dataplik:

Znaczenie danych zawartych w kolumnach

 

Kregkato               KA          Jan Kowalski                23           .98.              \3\              88

Kregkato               KA          Piotr Pawlak                23            .98.              \3\              88

Pregpod                PO         Krzysztof Wrak             25            .45.              \2\              77

Cregcent               CE          Jola Kruk                    19             .74               \1\              65

Mregmazu              MA         Urszula Kropiuk            14             .54.              \5\              85

Pregpod                PO         Zygmunt Malina            25            .45.              \2\               54

Wregwielko            WK        Marian Kluska               35             .98.              \4\              77

Greggda                 GD         Katarzyna  Polak          58             .69.              \9\              87

Cregcent                CE         Mariusz Pol                  19             .54.              \1\              77

 

przypominam, że po wpisaniu danych naciskamy przycisk [Esc] następnie wystukujemy :, który ukazuje się w dolnym lewym rogu i wprowadzamy polecenie   :wq . Plik  dataplik jest utworzony i możemy go zacząć testować przy pomocy polecenia grep zawierającego lub nie zawierającego wyrażenia regularne.

 

Przykłady:

grep  WK  dataplik

 Wregwielko                WK                 Marian Kluska 35            .98.              \4\               91

 

Wyjaśnienie: Na ekranie wyświetlają się linie zawierające wyrażenie regularne  WK znajdujące się w pliku dataplik

 

grep   ‘^C’  dataplik

Cregcent                      CE                   Jola Kruk                    19            .74               \1\              65

Cregcent                      CE                   Mariusz Pol                 19            .54.               \1\              25

Wyjaśnienie: Na ekranie wyświetlają się wszystkie linie zaczynające się od  „C”, symbol ^ pokazuje ,że szukamy wierszy które zaczynają się od znaku (czy wyrażenia regularnego) znajdującego się zanim . W tym przypadku jest to litera C.

 

grep  ‘4$’   dataplik

Pregpod                       PO                   Zygmunt Malina          25            .45.              \2\              54

Wyjaśnienie: Na ekranie wyświetlają się linie kończące się cyfrą „4”. Symbol  $ pokazuje, że poszukiwania znaków rozpoczynamy od końca wiersza. W tym wypadku znakiem tym jest cyfra 4.

$

 

$  grep  ‘4\. ’  dataplik

Cregcent                      CE                   Jola Kruk                    19            .74.              \1\               65

Mregmazu                     MA                  Urszula Kropiuk            14            .54.              \5\               85

Cregcent                      CE                   Mariusz Pol                  19            .54.              \1\               25

Wyjaśnienie: Na ekranie wyświetlają się linie zdefiniowane przez wyrażenie regularne  zawierające  zdefiniowane przez   ‘4\.  ‘  czyli wyszukujemy wierszy które zawierają cyfre cztery po której następuje kropka a następnie spacja.

 

$  grep  ‘\\3\\’  dataplik

Kregkato                     KA                  Jan Kowalski               23            .98.              \3\               88

Kregkato                     KA                  Piotr Pawlak               23            .98.              \3\               88

Wyjaśnienie: Na ekranie wyświetlają się linie zawierające cyfrę „3” obramowaną przez \3\

 

$  grep  ‘^[KW]’  dataplik

Kregkato                     KA                  Jan Kowalski               23            .98.              \3\               88

Kregkato                     KA                  Piotr Pawlak               23            .98.              \3\               88

Wregwielko                 WK                 Marian Kluska              35            .98.              \4\               91

Wyjaśnienie: Na ekranie wyświetlają się wszystkie linie zaczynające się o litery „K”  albo „W”.

 

$  grep ‘[A-Z][A-]  [A-Z][A-Z]

Kregkato                     KA                  AB Kowalski               23            .98.              \3\               88

Greggda                      GD                  DA  Polak                 58             .69.              \9\               87

 Wyjaśnienie: Na ekranie wyświetlają się linie zawierające dwie duże litery następujące natychmiast po sobie po których występuje spacja i znów dwie duże litery następujące natychmiast po sobie.

 

$  grep ‘ll* ‘  dataplik

Cregcent                      CE                   Jola Krul                     19            .74               \1\               65

Cregcent                      CE                   Mariusz Poll                 19            .54.              \1\               25

Wyjaśnienie: Na ekranie wyświetlają się linie zawierające małą literę „l” po której występuje zero lub więcej razy także mała litera „l” po której następuje spacja.

 

Polecenie Find

W tym podrozdziale omówimy szerzej – szczególnie z uwzględnieniem zastosowania w tym poleceniu wyrażeń regularnych - polecenie  find (szukaj) z którym zapoznaliśmy się już w rozdziale 3. Polecenie find jest w realnym świecie porównywane do szwajcarskiego zegarka. Narzędzie to potrafi przeszukać wszystkie wpisy w systemie plików i wyświetlać rezultaty spełniające zadane kryteria. Pod wieloma względami te właśnie duże możliwości kryteriów, które możemy zastosować w polecenie  find , przesądzają o potędze tego narzędzia.

Polecenie  find  jest bardzo przydatne do badania i wykonywania poleceń związanych z całą strukturą katalogów. Polecenie  find  przeszukuje system plików w dół począwszy od określonego katalogu, może również wykonywać podstawiając w nich jako argumenty wyszukane nazwy plików lub katalogów. Powtórzmy polecenie  find   prowadzi wyszukiwania plików lub katalogów według zadanych kryteriów od wskazanego katalogu „w dół” (jak pamiętamy struktura katalogu ma postać odwróconego drzewa), uwzględniając wszystkie podkatalogi, z czego wynika, ze jeżeli wskazanym katalogiem jest  root  ( / ) to wówczas przeszukujemy całą strukturę katalogów systemu Linux.

 

Polecenie  find  wyszukuje pliki w strukturze katalogu (katalogów) i może na wyszukanych plikach wykonywać różne operacje, dlatego strukturę polecenia find można przedstawić w następujący sposób:

find - w jakim katalogu wyszukujemy pliki – jakie kryteria selekcji – co robimy ze znalezionymi plikami ?

 

Weźmy najprostszy przykład: 

find  /……     →     oznacza, ze wyszukiwania będą odbywały się w całej strukturze katalogów.

find  /home…..     →     oznacza, że wyszukiwania będą odbywały się w katalogu domowym home.

 

Jakimi kryteriami selekcji dysponujemy w poleceniu   find ?

Kryteria → Funkcja

-name →  wyszukuje plik o określonej nazwie

-type → wyszukuje pliki, których typ jest określony jako: 

d  →  katalog

f  →  plik normalny

b  →  plik blokowy

c  →  plik znakowy

l  →  dowiązanie symboliczne

-path ‘wzorzec’ →  wyszukuje pliki, których ścieżka dostępu pasuje do wzorca

-links →  wyszukuje pliki z liczbą N dowiązań do plików

-size →  wyszukuje pliki, które mają wielkość N

-user →  wyszukuje pliki, które należą do użytkownika

-perm →  wyszukuje pliki, które mają prawa dostępu określone jako tryb

-atime →  wyszukuje pliki, które były otwierane w N dniach

-mtime →  wyszukuje pliki które zostały zmodyfikowane w N dniach

 

Co robimy z wyszukanymi plikami czyli jakie są kryteria egzekucji na plikach wyselekcjonowanych przez polecenie  find ?

-print →  przekazuje na standardowe wyjście nazwę odnalezionego pliku oraz jego pełną ścieżkę dostępu

-exec polecenie {}\; →  uruchamia polecenie dla odnalezionego pliku

-ok. polecenie {} \; →  potwierdza uruchomienie polecenia dla odnalezionego pliku

 

Z dotychczasowego wykładu wynika, że polecenie  find może przybrać postać niezwykle skomplikowaną, dlatego najlepszą metodą jego nauki będzie analiza poniższych przykładów, które stopniując trudność umożliwią uczniowi zapoznanie się z skomplikowana strukturą polecenia.

 

$  find  . –type  d

 Polecenie wyszukuje tylko katalogi znajdujące się w bieżącym katalogu (bieżący katalog jest oznaczony w poleceniu  „.”.

 

$ find . –name piotr1 –print

Polecenie to wyszukuje wszystkie pliki o nazwie piotr1

 

$ find . –type d  -print

Polecenie to wyszukuje tylko nazwy katalogów

 

$ find /home –name ‘*.c’ –print

Polecenie to wyszukuje wszystkie pliki których sufiks jest „.c”

 

$ find   ~  -name  ‘p*’ –print

W powyższym poleceniu tylda „~” oznacza katalog domowy użytkownika czyli punkt rozpoczęcia poszukiwań. Polecenie znalazło jeden plik którego nazwa zaczyna się na „p” (wzorzec p*).

 

Uwaga: czy możemy kryterium egzekucji –print, zastąpić używając innego wyrażenia; inaczej mówiąc czy możliwe jest uzyskanie tego samego rezultatu innym sposobem, wykorzystując dotychczas poznane polecenia i zasady obowiązujące w systemie Linux ? Tak, poznaliśmy w rozdziale III tzw. potok (pipe) i wykorzystując jego mechanizm, przy pomocy np. polecenia more lub cat, otrzymamy te same rezultaty

 

$ find . –name piotr1  |   more

$ find . –type d   |  more

$ find /home –name ‘*.c’  |  more

$ find   ~  -name  ‘p*’   |   more

 

Wniosek jest banalny ale bardzo ważny: ten sam rezultat możemy uzyskać stosując różne polecenia i różne mechanizmy wewnętrzne systemu operacyjnego Linux.

 

Polecenie  find może również sprawdzać warunki dotyczące nazwy i podejmować odpowiednie działania. Aby na przykład zmienić prawa dostępu wszystkich podkatalogów katalogu domowego /home, można wydać polecenie

$ find . –type  d –exec chmod 770  {} \;

Uwaga: używając opcji  -exec   należy zachować szczególna ostrożność ponieważ można po niej podać cokolwiek -  w tym polecenie mv, rm itd. Jeżeli zamiast opcji –exec użyjemy opcji –ok., przed każda operacją wymagane będzie potwierdzenie

 

$ find . –type d  -ok.  chmod  770 {} \;

find poprosi użytkownika o potwierdzenie , zanim wykona polecenie.

 

Dotychczas przedstawiliśmy względnie prostą postać polecenia find , w tej chwili wprowadzimy jeszcze dwie dodatkowe grupy kryteriów.

 

Pierwszym z nich są parametry kryteriów, które wyrażają ilość lub wielkość mogą one przybierać trzy różne formy:

1. Kryterium n oznacza dokładnie liczba symbolizująca n, tak więc „-ctime 5” wyraża że plik był utworzony 5 dni temu

2. Kryterium –n oznacza, mniejszy od liczby symbolizującej n, tak więc „-size -1000”, wyszukuje pliki których objętość jest mniejsza od 1000 octetów

3. Kryterium +n oznacza, większy od liczby symbolizującej n, tak więc „-size +1000” wyszukuje pliki których objętość jest większa od 1000 octetów.

 

Drugim z nich są parametry logiczne, które np. mogą wiązać wiele kryteriów wyborów; z definicji operatorem logicznym wiążącym różne kryteria wyboru jest ET (i), jednak istnieją także inne operatory:

Operator logiczny                Jego oznaczenie w poleceniu  find

ET                                         -a

OU                                         -o

NON                                        !

(wyrażenie)                             \(wyrażenie\)

 

Kontynuujemy wyjaśnianie działanie polecenia   find na przykładach:

$ find /home  -mtime 0 –print

$ find /home –type f  -size 0 –exec rm –f {}\;

 

Polecenie wyszukuje i niszczy wszystkie pliki, których objętość wynosi 0 octetów, czyli pliki puste. Zwróćmy uwagę, że te – jego rezultaty - polecenie można uzyskać w inny sposób:

$ rm  ‘find /home –type f –size 0  -print’

$ find /home ! –user piotr1 \( -size +10000c –o –atime -30\)

Polecenie wyszukuje pliki których właścicielem (użytkownikiem) nie jest  piotr1 i których objętość nie przekracza  10000 octetów i które używano przed 30 dniami

 

$ find  .  –mtime  +20  -exec  rm {}  \;

Polecenie to pozwala wymazać pliki, które nie były modyfikowane od więcej niż 20 dni.

 

To samo można wyrazić za pomocą:

$ rm  ‘find . mtime  +20  -print’

 

 

Załóż własną stronę internetową za darmo Webnode