Nie taki Unix straszny (4)

W kolejnym, czwartym już odcinku opowieści o Unixie chciałbym przedstawić dwa polecenia, będące jednymi z najważniejszych narzędzi w Unixie. Są tą rozkazy find i grep.

W kolejnym, czwartym już odcinku opowieści o Unixie chciałbym przedstawić dwa polecenia, będące jednymi znajważniejszych narzędzi w Unixie. Są tą rozkazy find i grep.

Za pomocą pierwszego z tych poleceń można szukać wszelkich plików, których metryka spełnia podane warunki. Polecenie find to taki ulepszony i bardziej uniwersalny program FileFind z DOS-owego Norton Utilities.

Programy możemy poszukiwać wedle ich nazwy (parametr -name), właściciela ( -user), typu ( -type), wielkości (-size), czasu kiedy zostały stworzone lub ich zawartość była modyfikowana, bądź tylko wykorzystana (-mtime, -atime,- newer). Przykładowo: polecenie find -newer file1 służy do poszukiwania plików modyfikowanych nie dawniej niż plikfile1; find -atime +5 znajduje pliki niewykorzystywane co najmiej od pięciu dni, a find -mtime -5 te, których zawartość była zmieniana nie dawniej niż w ciągu ostatnich pięciu dni.

Polecenie find wywołuje się z parametrami w następującym porządku:

- część dysku, którą chcemy przeszukać (lista kartotek)

- warunki, jakie mają spełniać poszukiwane pliki

- polecenia dotyczące znalezionych plików

Na przykład polecenie:

find / -name pegam -print

Znajdzie wszystkie pliki użytkownika o nazwie pegam, przeszukując cały dysk, poczynając od katalogu głównego('/'), wypisując nazwy znalezionych plików (lub katalogów) na ekranie (opcja -print). Jeśli pegam jest identyfikatoremużytkownika systemu, powinny pokazać się nazwy przynajmniej dwu katalogów - prywatnego i katalogu, w którym trzymana jest jeszcze nieprzeczytana, otrzymana poczta dla użytkownika (na ogół jest to coś w postaci:

.../spool/mail/pegam).

Ponieważ do wielu katalogów możemy nie mieć prawa wstępu, w trakcie poszukiwania program find będzie zaśmiecał ekran komunikatami w stylu:

Cannot chdir to : nazwa_katalogu: Permission denied

Możemy tego uniknąć, nieco modyfikując powyższe polecenie:

find / -name pegam -print 2> /dev/null

Katalog /dev/null występuje w każdym Unixie i jest to swego rodzaju ściek, do którego każdy może pisać co mu się żywnie podoba (wrzucacamy tam właśnie wyżej przedstawione meldunki), a próba odczytu za każdym razem da w efekcie znak końca pliku. Tajemniczy znaczek 2> to skierowanie strumienia błędów właśnie do tego katalogu. Tu mała dygresja - w Unixie tradycyjnie mamy standardowo strumień danych wejściowych (stdin - klawiatura - numer 0), wyjściowych (stdout - monitor - numer 1) i błędów (stderr -monitor - numer 2). Omówione poprzednioi symbole '>','>>' to właśnie zmiana strumienia wyjściowego (na plik), przy czym tak naprawdę jest to zapis '1>' i '1>>', tylko'1' domyślnie opuszczamy. Oznaczenie '2>' to skierowanie strumienia błędów do pliku.

Na ogół warto w poleceniu find, aby uniknąć niejednoznaczności, ujmować nazwy w apostrofy (np. tutej:'pegam').

Warunki poszukiwania można łączyć, wprowadzając operatory logiczne koniunkcji, alternatywy lub negacji. Koniunkcji używamy wtedy, gdy zależy nam na jednoczesnym spełnieniu warunków. Wprowadzamy wtedy kolejne warunki oddzielając je zwyczajnym odstępem (spacją). Dla alternatywy (gdy musi być prawdziwy przynajmniej jeden warunek) jest to opcja -o (ang. or). Winno się wówczas ująć całe wyrażenie w nieco dziwnie wyglądające nawiasy, w postaci: ' \( ' z lewej i ' \) ' z prawej. Dla negacji dany warunek poprzedzamy symbolem '!'. Np. polecenie:

find / ! \( -mtime -30 -o -type d )\ -print

znajdzie wszystkie pliki nie będące katalogami, których zawartość nie była zmieniana od 30 dni.

Możemy użyć nazw znalezionych plików, jako argumentów dowolnych poleceń Shell'a, używając parametru -exec, np. w postaci zapisanej, jako część całego polecenia find:

find / -user 'pegam' -exec rm {}

Usunie to wszystkie znalezione pliki, należące do użytkownika 'pegam' (symbol '{}' to pole, w które polecenie find wstawi odpowiednie nazwy znalezionych plików, a '\' ogranicza obszar działania -exec (wewnątrz, którego mogąwystępować dowolne polecenia Shell'a)

Grep

Warto zapoznać się także z poleceniem grep, które wyszukuje w pliku wiersze spełniające dany wzorzec (por. opis programu grep pod DOS'm, CW nr 25 z 22 Czerwca 1992 r.). Nazwą tego polecenia jest skrót wyrażenia Global Regular Expression Print. Z jego pomocą możemy wyszukiwać wszelkie teksty zawierające podany wzorzec w postaci wyrażenia regularnego (to termin zaczerpnięty z teorii automatów skończonych, w uproszczeniu są to wyrażenia, będące ciągami znaków, które można prosto zdefiniować). Możemy określić długość wyrażenia i znaki wchodzące w jego skład (podając zakres do jakiego należą lub explicite sam tekst.

'.' to dowolny znak

'*' zastępuje grupę znaków (dowolnej długości)

w nawiasach '[' i ']' podaje się zakres do jakiego może należeć dany znak, np.:

[afk] - to albo a, albo f, albo k

[a-k] - to wszystkie kolejne litery od małego a do k

'[a-b].c[A-Za-z]' - to wszystkie czteroznakowe słowa, zaczynające się na 'a' lub 'b', kończące się dowolnąliterą, a przedostatnim ich symbolem ma być litera 'c' (czyli np. "baca", "a9cZ" itd.). Można odwrócić działanie polecenia grep (czyli znaleźć wszystkie te wiersze, w których dany wzorzec nie występuje), używając parametru -v.

Znaczek '^' to albo oznaczenie początku wiersza, albo (gdy występuje jako sekwencja '[^' zaprzeczenie danego warunku, np.:

'^[0-1]' - to wiersze zaczynające się od jakiejś cyfry

'[^0-7] - to słowa nie zaczynające się od cyfry

Opcja -w każe znajdować tylko te wiersze, w których wzorzec występuje jako samodzielne słowo, a nie jego część.

np. polecenie:

grep -v file1 '^[A-Za-z]'

wybierze z pliku file1 wszystkie wiersze zaczynające się od znaku nie będącego literą.

Spróbujmy dokonać fuzji dwu omówionych poleceń, pisząc:

find / -name '*.txt' -exec grep Unix {} >> WierUni

Działanie winno być następujące - znalezione zostaną wszystkie pliki o rozszerzeniu *.txt, wybrane z nich wiersze, w których występuje słowo Unix i przesłane do pliku WierUni.

Po kolei: find to polecenie poszukiwania; / oznacza, że każemy szukać we wszystkich katalogach, od głównego poczynając; -name pokazuje, że chodzi nam o pliki o danej nazwie czyli '*.txt'; -exec to polecenie wykonania rozkazu (programu) Shell-a; grep to właśnie takie polecenie systemowe; Unix to argument polecenia grep (słowa jakie chcemy znaleźć), {} to parametr, w miejscu którego znajdzie się nazwa znalezionego pliku; >> to dopisanie na końcu pliku WierUni wyniku działania programu grep (czyli interesujących nas wierszy); \ zamyka fragment, opisujący działanie opcji - exec. Jeśli ktoś się zgubił nie ma co się przejmować, to trzeba poćwiczyć.

Czy można zapisać to polecenie w innej postaci, z użyciem strumieni danych?

find / -name '*.txt. | grep Unix >> WierUni

Niestety nie, bowiem efekt tak wydanego polecenia będzie całkiem inny. Do pliku WierUni zostaną przesłane wszystkie nazwy plików zawierające słowo Unix (bo to ich nazwy są właśnie wynikiem działania polecenia find). Takie użycie polecenia grep jest dość często spotykane (jako filtru przetwarzającego wyjście jakiejś innej komendy, bądź programu).

Jak łatwo zauważyć, podstawym składnikiem filozofii Unix'a jest dostarczenie użytkownikowi pewnych elementów-cegiełek, z których może on budować polecenia lub programy wsadowe, wykonujące całkiem skomplikowane funkcje. Zamiast mieć ileś tam programów, w obrębie których, korzystając z ich wewnętrznych menu, użytkownik może wykonać pewne działania, Unix daje do ręki polecenia systemowe, z których tworzyć można konstrukcje robiące to, czego się oczekuje. Niestety konsekwencją tego jest żmudna, długotrwała nauka i konieczność ciągłego korzystania z podręcznika (co jest raczej mało pasjonującym zajęciem). Rozbudowane polecenia zaczynają wyglądać (z daleka), jak nie przymierzając, szlaczki w zeszycie pierwszoklasisty. Na ogół stają się one jakimś nieestetycznym ciągiem literek, minusów, plusów, slash-ów i backslash-ów,... itd. Obciąża się użytkownika pamiętaniem tysiąca i jeden szczegółów, nieistotnych dla rozwiązywanego problemu i w istocie traci się przez to chwilami trochę poczucie co jest celem, a co środkiem.

No cóż, dzięki swym możliwościom pracy wielozadaniowej i wielodostępnej, swemu rozpowszechnieniu, bogactwu i sile zawartych narzędzi, Unix potęgą jest i basta! W pewnym momencie, dla pewnych zastosowań kończą się możliwości Peceta i trzeba użyć <poważnych> komputerów, z <poważnym> systemem operacyjnym, a takim bez wątpienia jest Unix.

W celu komercyjnej reprodukcji treści Computerworld należy zakupić licencję. Skontaktuj się z naszym partnerem, YGS Group, pod adresem [email protected]

TOP 200