Linux Articles February 10, 2008 8

Co to jest BASH Kurs BASH

Bash to powloka systemowa UNIX napisana dla projektu GNU. Nazwa jest akronimem od Bourne-Again Shell (ang. znowu shell Bourne’a). Jest to jedna z najpopularniejszych powlok systemów uniksowych. Wywodzi sie od powloki Bourne’a sh, która byla jedna z pierwszych i najwazniejszych powlok systemu UNIX, i zawiera pomysly zawarte w powlokach Korna i csh. Pierwotna powloka Bourne’a byla tworzona przez Stephena Bourne’a. Bash byl pisany glównie przez Briana Foxa i Cheta Rameya. Powloka Bournea sh zostala stworzona okolo roku 1977. Powloka bash zostala napisana w roku 1987 przez Briana Foxa. W roku 1990 jej glównym opiekunem zostal Chet Ramey. Bash jest domyslna powloka w wiekszosci dystrybucji systemu Linux oraz w systemie Mac OS X w wersji 10.4 Tiger. Istnieja takze wersje dla wiekszosci systemów Unixowych. Bash jest takze domyslna powloka w srodowisku Cygwin dla systemów Win32. Program jest rozprowadzany na licencji GPL. Bash jest bardzo dobrym jezykiem skryptowym, sluzacym do efektywnego zarzadzania systemem.

Skrypt to nic innego jak zwykly jawny nie skompilowany plik tekstowy zawierajacy rózne instrukcje, polecenia systemowe, do wykonania przez zdefiniowany w skrypcie interpreter powloki systemowej (/bin/bash). Zadaniem powloki jest przetlumaczenie ich na polecenia systemu. Jesli ktos mial do czynienia z plikami wsadowymi (Batch) w systemie DOS to wlasnie skrypty sa tego typu plikami.

Kurs BASH

Spis Tresci

Hello World i wykonanie skryptuTradycyjnie pierwszym krokiem do pisania wlasnego kodu jest wyswietlenie na standardowym wyjsciu (stdout), tutaj ekran monitora, oslawionego tekstu “Hello World”.

Zakladajac ze pracujemy np. w Linuksowej konsoli, w której mamy za powloke obrana wlasnie powloke bash wystarczy wydac komende:

echo "Hello World"

Na wyjsciu dostaniemy w odpowiedzi napis Hello World. Dlaczego tak sie dzieje? Otóz pracujac w powloce bash od razu jestesmy w srodowisku w którym wykonujemy kod – powloka interpretuje bezposrednio polecenia dla niej zrozumiale i natychmiast podaje nam wynik dzialania instrukcji na nasz ekran. A teraz do rzeczy. Napiszmy prosty skrypt który wlasnie wydrukuje nam na nasz ekran monitora nasze Hello World.

Kazdy skrypt powinien zawierac na poczatku zdefiniowany rodzaj shella w jakim skrypt ma byc wykonany:

#!/bin/bash lub krócej #!/bin/sh

tutaj skrypt zawsze bedzie wykonywany przez interpreter polecen bash, niezaleznie od tego jakiej powloki w danej chwili uzywamy. Przykladowo pracujemy w powloce csh, skrypt na czas wykonania zawartego w nim kodu wywola powloke bash:

tworzymy plik tekstowy o nazwie hello.sh

touch hello.sh

 nastepnie edytujemy utworzony plik dowolnym edytorem np. pico, vi, vim, joe:

pico hello.sh

#wypelniamy nasz pusty plik ponizszym kodem:

#!/bin/bash
#Nastepnie piszemy kod:

echo "Hello World"

#koniec skryptu

 Uwaga:

“#” oznacza komentarz w skrypcie. Interpreter kodu pomija wszystko zawarte za # do konca linii, mozemy w ten sposób zamieszczac w skrypcie swoje komentarze.
Zapisujemy zmiany i oto mamy swój pierwszy skrypt, który nalezy uruchomic. Jest kilka sposobów na uruchamianie skryptów. Wiele poradników nakazuje nadac plikowi prawo wykonania aby go uruchomic – owszem jest to poprawne jednak nie niezbedne, skrypty mozemy uruchamiac na kilka sposobów, najprostszy sposób uruchomienia skryptu to wydanie komendy sh (dla bash): sh skrypt.sh – taki sposób uruchamiania skryptu pozbawia nas potrzeby umieszczania na poczatku kodu definicji powloki #!/bin/bash, poniewaz sh oznacza: wykonaj skrypt w powloce bash. Jezeli nie podamy w skrypcie definicji powloki, ani tez nie wykonamy skryptu poleceniem sh, skrypt nasz zostanie wykonany w domyslnej powloce w jakiej wlasnie jest wywolywany, w linuksie zazwyczaj domyslna powloka jest bash.

W naszym przykladzie zakladajac ze jestesmy w tym samym katalogu co nasz skrypt wydajemy polecenie:

sh hello.sh

w przeciwnym wypadku musimy podac pelna sciezke dostepu do skryptu:

sh /home/user/skrypty/hellish

 co nam wyswietli na wyjsciu, na monitorze tresc:

Hello World

Inny sposób wykonania skryptu, to nadanie mu prawa, atrybutu do wykonania czyli:

chmod + x hello.sh

nastepnie aby wykonac skrypt wystarczy wydac polecenie:

./hello.sh

#lub

. /home/user/skrypty/hello.sh

 

Kolejnym sposobem uruchamiania skryptów jest nadanie im praw do wykonania i umieszczenia sciezki do skryptu w zmiennej PATCH, lub np. skopiowanie skrytu do katalogu /usr/sbin, wtedy wykonujemy nasz skrypt tak jak inne programy zawarte w naszym systemie, wydajac po prostu polecenie:

hello.sh

Nazwa naszego pliku hello.sh posiada rozszerzenie .sh które nie jest konieczne, jednak dobrym nawykiem jest nadawanie skryptom rozszerzen w celu latwiejszego ich identyfikowania przez nas samych jak i przez róznego rodzaju edytory podswietlajace skladnie kodu, np. edytor zawarty w midnight commanderze rozpoznaje rodzaj kodu po rozszerzeniu pliku i w sposób wygodny dla nas podswietla skladnie kodu podczas edycji skryptu.

  • Ciekawostka:

Ogólnie #!/bin/powloka wcale nie musi byc powloka, moze byc dowolnym poleceniem, np. nastepujacy skrypt sam sie kasuje:

#!/bin/rm

#Zawartosc skryptu nie jest istotna
#jakies tam polecenia

#End script

Powloka rozwinie to nam w /bin/rm ./nazwa_skryptu, czyli skasuj hello.sh

Do spisu tresci

Polecenie ECHO

Echo jest poleceniem wyswietlajacym na ekranie swoje argumenty.

Skladnia:
#!/bin/bash

echo "jakis tekst" #wydrukuje na ekranie: jakis tekst

#End script

 

Parametry ECHO:

-n
-e
a
b
c
e
f
n
r
t
v
\
nnn
xnn
: nie jest wysylany znak nowej linii (kursor pozostaje w tej  samej linii)
: wlacza inetrpretacje znaków specjalnych takich jak:
: alert, brzeczyk systemowy
: backspace
: to samo co -n
: escape
: line feed
: form feed czyli wysuw strony, nowa linia
: znak nowej linii powrót karetki (fr daje to samo co n)
: tabulacja pozioma
: tabulacja pionowa
: backslash
: znak, którego kod ASCII ma wartosc ósemkowa
: znak, którego kod ASCII ma wartosc szesnastkowa

Przyklad:

echo -n "przykladowy tekst"

 

Jako ze w powloce znak backslash jest znakiem specjalnym, musimy go podwoic, badz wpisywac ciagi znaków w cudzyslowach.

Przyklad:

#!/bin/sh echo -e \a

sleep 1 #wstrzymanie skryptu na 1 sekunde
echo "peep"
echo -e "a"

 

Here-Documents
‘Here documents’ – dokumenty miejscowe. Jest to rodzaj przekierowania, które pozwala czesc tresci skryptu traktowac jako standardowe wejscie.

Skladnia:

<
here-document
ogranicznik

Przyklad:

#!/bin/sh
cat << KONIEC

Ten tekst zostanie
wyswietlony na ekranie
ogranicznikiem jest KONIEC

KONIEC

 Po wykonaniu powyzszego skryptu otrzymamy na ekranie wszystko to co zawarlismy miedzy wyrazami KONIEC. Ten sposób moze byc uzywany do wyswietlenia wiekszej ilosci informacji na ekran bez koniecznosci wpisywania echo w kazdej linii. W dokumencie miejscowym dokonuje sie wszystkich rozwiniec. Ogranicznik koncowy musi znalezc sie sam w jednej linii, dlatego ostatnie slowo KONIEC pojawia sie na ekranie. Pierwszy ogranicznik moze byc dowolnym wyrazeniem, szczególy w podreczniku systemowym.

 

Slowa zastrzezone

(ang. reserved words)Tak jak w kazdym jezyku programowania tak samo i w bashu wystepuja slowa zastrzezone, zarezerwowane, które maja dla powloki specjalne funkcjonalne znaczenie, wtedy gdy nie sa cytowane. Glówne slowa to:

! case do done elif else esac fi for function if in select then until while { } time [ ]

Do spisu tresci

Polecenie sleep i exit

Polecenie sleep powoduje wstrzymanie wykonywania instrukcji skryptu na okreslony czas:

#!/bin/bash

echo "teraz wstrzymam skrypt na 10 sekund"
sleep 10
echo "koniec papa..."

#End script

 

Polecenie exitPolecenie exit powoduje natychmiastowe zakonczenie skryptu bez wzgledu na miejsce wywolania. Dodatkowy parametr pozwala udostepnic otoczeniu kod wyjscia, który moze nalezec do przedzialu 0 – 125, przy czym zero jest traktowane jako sukces. Kody powyzej 125 sa zarezerwowane i maja nastepujace znaczenie:

Kody wyjecia > 125
126 – plik nie mial atrybutu wykonywalnosci “x”
127 – nie znaleziono pliku o zadanej nazwie
128 i w góre powodem zakonczenia byl jakis sygnal (wartosc kodu wyjscia równa jest 128 + numer sygnalu)

Piszac skrypty niejednokrotnie zalezy nam aby skrypt po zakonczeniu pracy, w zaleznosci od tego jakie czesci skryptu sie wykonaly zwrócil odpowiedni status. A wiec jesli skrypt zakonczyl dzialanie bez bledu zwróci nam status 0, natomiast jak cos pójdzie nie tak zwróci 1. A co jezeli polowa skryptu wykona sie prawidlowo natomiast druga nie wykona sie wcale a my chcemy o tym wiedziec – wtedy mozemy zastosowac exit z odpowiednimi statusami.

Przyklad:
#!/bin/bash

#przenies zosia na mundek (zmien nazwe)

mv zosia mundek
if [ $? -eq 0 ]
 then echo "Powodzenie"
 else echo "blad"; exit 4
fi

#tutaj moze byc dalsza czesc skryptu do wykonania

echo "papa"

#End script

 

Jezeli np. plik zosia nie istnieje to mamy niepowodzenie w wykonaniu skryptu i chcemy zeby w takim przypadku skrypt po zakonczeniu zglosil kod 4. Jezeli natomiast polecenie mv zadziala bez bledu to zwróci kod 0, instrukcja if sprawdzi czy status dzialania polecenia mv jest równy 0 i wyswietli powodzenie, oraz skrypt bedzie wykonywany dalej i zakonczy sie powodzeniem i statusem 0, w przeciwnym wypadku wykona sie druga czesc instrukcji – skrypt wyswietli tekst “blad” i wykonujac polecenie exit ze statusem 4 przerwie dzialanie a dalsza czesc skryptu juz se nie wykona.

Do spisu tresci

Potoki i przekierowania

Potoki i przekierowania pozwalaja zmieniac standardowe wejscie, wyjscie oraz standardowe wyjscie bledów lub laczyc je w potoki. Mozna przekierowywac dowolne z deskryptorów, jednak w wiekszosci przypadków wykorzystywane sa jedynie na standardowych wejsciach i wyjsciach.

Skladnia potoku:

polecenie1 | polecenie2 | polecenie3 | polecenien…

Potok jest ciagiem polecen porozdzielanych znakiem “|”, przy czym standardowe wyjscie polecenia poprzedzajacego jest standardowym wejsciem polecenia nastepnego.

Przyklad:

$ /sbin/ifconfig | grep HWaddr > wynik.txt

 Jak widac pierwsze polecenie wywoluje polecenie ifconfig nastepnie polecenie drugie – program grep wyodrebnia z wyniku dzialania ifconfig jedynie linie zawierajaca adres MAC karty sieciowej i caly wynik dzialania potoku jest zapisywany do pliku o nazwie wynik.txt – ta ostatnia operacja to wlasnie przekierowanie…

Przekierowania

Deskryptor (ang. descriptor) – struktura definiujaca okreslony obiekt w pamieci.

Przed wykonaniem polecenia powloka sprawdza, czy nie powiazac okreslonych deskryptorów innymi, badz z plikami. Przekierowanie wejscia [n] < plik powoduje otwarcie pliku do czytania i powiazanie deskryptora o numerze n z zawartoscia pliku. Jesli pominiemy numer deskryptora powloka przekieruje standardowe wejscie (deskryptor nr 0).

Przyklad:

$ mail [email protected] This e-mail address is being protected from spambots, 
you need JavaScript enabled to view it < wiadomosc.txt

 

Przekierowanie wyjscia [n] > plik powoduje otwarcie pliku do pisania i powiazanie go z deskryptorem o numerze n. Jesli plik nie istnieje zostanie stworzony, jesli istnieje zostanie skrócony do zera (patrz opcja noclobber). Gdy pominiemy numer deskryptora powloka przekieruje standardowe wejscie (deskryptor nr 1). Przekierowanie wyjscia z dopisywaniem [n] >> plik powoduje otwarcie pliku do dopisywania (jesli nie istnieje zostanie stworzony) i powiazanie go z deskryptorem o numerze n. Gdy pominiemy numer deskryptora powloka przekieruje standardowe wejscie. Przekierowanie wyjscia i standardowego wyjscia &> plik powoduje otwarcie pliku do pisania i powiazanie go ze standardowym wyjsciem i standardowym wyjsciem bledów. Powyzsze definicje nie zbyt jasno tlumacza róznice miedzy przekierowaniem wyjscia i wejscia. Na przekierowanie wejscia mozna patrzec w ten sposób, ze czytajac z danego deskryptora bedziemy czytali z pliku, a w przypadku przekierowania wyjscia piszac do danego deskryptora wynik znajdzie sie w pliku. Przekierowan wejscia rzadziej sie uzywa, gdyz wiekszosc polecen pozwala podac jako parametr plik wejsciowy zamiast standardowego wejscia.

Przyklad:

$ find / -size +500k -xdev >& duze_pliki

Wpisujac powyzsza linijke w pliku duze_pliki dostaniemy liste plików biezacego systemu plików zajmujacych conajmniej 500 kilobajtów. W pliku tym zostana tez umieszczone komunikaty o bledach. Duplikowanie deskryptorów. Wywolanie [n] && [m] piszac do deskryptora [n] piszemy do deskryptora [m].

Przyklad:

$ find / -size +500k -xdev > duze_pliki 2>&1

Wywolanie to jest równowazne wczesniejszemu. Standardowe wyjscie jest powiazane z plikiem duze_pliki, a standardowe wyjscie bledów ze standardowym wyjsciem – prosciej jesli chcemy wyeksportowac do tego samego pliku wynik dzialania programu wraz z bledami stosujemy takie wlasnie przekierowanie 2>&1.

Opcja “noclobber”Wlaczenie opcji:

set -o noclobber lub set -C

 Po wlaczeniu tej opcji jesli w przekierowaniach &gr; plik i >& plik plik istnieje, to zostanie wyswietlony blad. Zabezpiecza to przed przypadkowym nadpisaniem istniejacego pliku. Aby zapisac do istniejacego pliku nalezy wylaczyc opcje ‘noclobber’ (set +o noclobber lub set+C) lub tez uzyc przekierowania >| plik.

Przyklad:

$ touch plik
$ set -o noclobber
$ ls > plik
bash: plik: cannot overwrite existing file
$ ls >| plik
$ set +C
$ echo koniec > plik

Do spisu tresci

ZmienneW przeciwienstwie do wiekszosci jezyków programowania w skryptach nie deklaruje sie zmiennych przed ich zastosowaniem. Ich pierwsze uzycie jest jednoczesnie ich deklaracja. Nazwa zmiennej moze byc dowolnym identyfikatorem, przy czym wazna jest wielkosc liter i zmienne VARIABLE i variable sa rózne. Aby odwolac sie do zawartosci zmiennych trzeba przed nazwa zmiennej napisac znak $. Istotne jest takze to, ze zmienne sa pamietane przez powloke jako ciagi znaków, dopiero odpowiednie polecenia interpretuja te ciagi w odpowiedni sposób

Przyklad:

$ ile=5
$ echo ile
ile
$ echo $ile
5
$ ile=5+5 # 5+5 jest ciagiem znaków
$ echo ile
5+5
$

Do spisu tresci

Zmienne srodowiskowe

W skrypcie mozemy sie odwolac do zmiennych srodowiskowych w sposób identyczny do zwyklych zmiennych, piszac znak dolara przed nazwa zmiennej. Aby zobaczyc liste zmiennych zdefiniowanych w systemie wpisz w powloce polecenie env.

Przykladowe zmienne:
$HOME
$PATH
$PS1
$IFS
: katalog domowy uzytkownika
: lista katalogów przeszukiwana przez polecenia
: znak zgloszenia powloki
: separator pola wejscioweg, wszystkie znaki z tej zmiennej uzywane sa do oddzielania slów na wejsciu
$ IFS=":"
$ read x y z
1:2:3
$ echo x=$x y=$y z=$z
x=1 y=2 z=3

$ read x y z
1 2 3
$ echo x=$x y=$y z=$z
x=1 2 3 y= z=

$ IFS=" :"
$ read x y z
1:2 3
$ echo x=$x y=$y z=$z
x=1 y=2 z=3

$ IFS=":,"
$ read x y z
1,2:3
$ echo x=$x y=$y z=$z
x=1 y=2 z=3

$ read x,y,z *
1:2:3
bash: read: `x,y,z`: not a valid identifier

$ d=`x,y,z`
$ read $d **
1:2:3
$ echo x=$x y=$y z=$z
x=1 y=2 z=3

$ read "$d" ***
1:2:3
bash: read: `x,y,z`: not a valid identifier

 

Kilka ostatnich linijek z pewnoscia wprowadzilo troche zamieszania i wymaga wytlumaczenia. Powloka przeszukuje rezultaty rozwiniec parametrycznych, rozwiniec polecen w apostrofach i rozwiniec arytmetycznych w poszukiwaniu znaków ze zmiennej IFS { (*)-nie jest rozwinieciem}. Jesli takie znajdzie zamienia je na spacje (**). Jesli jednak calosc ujmiemy w cudzyslowy nie dojdzie do zamiany (***).

#!/bin/sh
IFS=:
echo "$*"
echo $*
echo $@
echo $1 $3
Wykonujac skrypt z parametrami: raz dwa trzy otrzymamy wynik:
raz:dwa:trzy
raz dwa trzy
raz dwa trzy
raz trzy
Polecenie unset
Polecenie unset anuluje przypisania zmiennym wartosci usuwajac te zmienne ze srodowiska.
Mozna równiez je stosowac do funkcji.
Przyklad:
$ zmienna=5
$ echo $zmienna
5
$ unset zmienna
$ echo $zmienna
$

Do spisu tresci

Polecenie EXPORT

To co przypiszemy zmiennym ginie po jego zakonczeniu, a to dlatego, ze uruchamiajac skrypt dostajemy nowe srodowisko i wszelkie przypisania zmiennych dotycza tego srodowiska. Uruchamiajac jakis inny proces z naszego skryptu dziedziczy on nasze srodowisko, ale po zakonczeniu skryptu wszystko znika. Istnieje jednak polecenie export, któro pozwala zmienic srodowisko procesu rodzica. Czesto to polecenie jest wykorzystywane w pliku konfiguracyjnym powloki (np. dla bash’a bedzie to /etc/bashrc i w katalogu uzytkownika .bashrc).

Skladnia:

export zmienna

lub

export zmienna=wartosc

Przyklad:

export PATH=$PATH:$HOME/bin
export DISPLAY=localhost:10.0

export ORACLE_BASE=/u01/app/oracle
ORACLE_HOME=$ORACLE_BASE/product/11.0.2
export ORACLE_HOME

 

Zmienne parametryczne:

$?
$$
$0
$#
$*
$@
$1,$2..
– Kod powrotu ostanio wykonywanego polecenia
– PID procesu biezacej powloki
– nazwa wykonywanego skryptu
– liczba przekazanych parametrów
– lista parametrów porozdzielanych pierwszym znakiem ze zmiennej $IFS, przyklad poniezej
– lista parametrów porozdzielanych spacjami
– poszczególne parametry w kolejnosci podanej przy uruchamianiu skryptu

Przyklad:

#!/bin/sh
IFS=:
echo "$*"
echo $*
echo $@
echo $1 $3

Wykonujac skrypt z parametrami: raz dwa trzy otrzymamy wynik:

raz:dwa:trzy
raz dwa trzy
raz dwa trzy
raz trzy

 

Polecenie unset

Polecenie unset anuluje przypisania zmiennym wartosci usuwajac te zmienne ze srodowiska.
Mozna równiez je stosowac do funkcji.

Przyklad:

$ zmienna=5
$ echo $zmienna
5
$ unset zmienna
$ echo $zmienna
$

Do spisu tresci

Cudzyslowy i apostrofy

Cudzyslowy

Istnieja dwa rodzaje cudzyslowów: ” ” (podwójne) i ‘ ‘ (pojedyncze). Istnieja jeszcze ( ` ) (apostrofy) omówione w nastepnym rozdziale. Cudzyslowów umozliwiaja przypisanie zmiennej ciagu zawierajacego spacje. Normalnie powloka traktuje spacje jako separatory parametrów. Jesli w poprzednim skrypcie chcielibysmy przekazac jako parametr ciag zawierajacy spacje, musielibysmy wywolac skrypt nastepujaco:

./nazwa_skryptu raz 'dwa trzy' cztery

co po wykonaniu daloby nam:

raz:dwa trzy:cztery
raz dwa trzy cztery
raz cztery

 

Cudzyslowy ” ” i ‘ ‘ róznia sie tym, ze w przypadku tych pierwszych powloka rozwija wszystkie nazwy zmiennych w wartosci tych zmiennych (rozwiniecia parametryczne), rozwija tez polecenia w apostrofach (patrz Apostrofy dalej) oraz odpowiednio traktuje pewne znaki poprzedzone backslashem ”. Nie jest tak w przypadku drugich apostrofów. Dodatkowo jesli chcemy miedzy cudzyslowami ” ” uzyc tego samego cudzyslowu, musimy poprzedzic go backslashem . Nie dotyczy to cudzyslowów pojedynczych, gdyz znak cudzyslowu po backslashu bedzie traktowany jako koniec lancucha. Nic nie stoi jednak na przeszkodzie, by wewnatrz cudzyslowów ” ” uzywac ‘ ‘ i odwrotnie. Aby nie doszlo do rozwiniecia zmiennej w cudzyslowach podwójnych mozemy znak dolara poprzedzic backslashem . Aby otrzymac backslash musimy napisac go podwójnie. Oczywiscie w cudzyslowach pojedynczych nie dojdzie do zadnego rozwiniecia.

Przyklad:

$ kat='$HOME'
$ echo $kat
$HOME
$ echo "$HOME"
$HOME
$ kat="$HOME"
$ echo $kat
/home/radek
$ kat='Cudzyslów " podwójny'
$ echo $kat
Cudzyslow " podwójny
$ kat="Cudzyslów " podwójny"
Cudzyslów " podwójny

 

Ponizej wymienione sa sekwencje poprzedzone backslashem zamieniane wewnatrz cudzyslowów podwójnych.

Pozostale sekwencje poprzedzone backslashem (wymienione przy poleceniu echo) nie sa zamieniane.

Apostrofy

Apostrofy ( ` ` ) maja calkiem odmienne od cudzyslowów znaczenie.

Powloka wykonuje polecenie zawarte miedzy nimi, a wartoscia wyrazenia jest wynik dzialania tego polecenia.

$ data=`date`
$ echo $data
Sun Sep 24 22:37:46 2000

#Zamiast dwóch apostrofów mozna zamiennie uzyc konstrukcji: $( ), np.:
data=$(date)

 

Podstawienia komend mozna zagniezdzac.

Do spisu tresci

Obliczanie Wyrazen

Aby obliczyc wyrazenie mozemy skorzystac z zewnetrznego polecenia expr lub uzyc wewnetrznej konstrukcji BASH’a, która jest szybsza gdyz nie potrzebuje oddzielnego procesu i jest wygodniejsza w uzyciu. Czasami trzeba jednak uzyc ‘expr’, dlatego zostanie pózniej zaprezentowane.

Tych operatorów mozemy uzywac w nastepujacych konstrukcjach:

$((wyrazenie))
((wyrazenie))
let wyrazenie

Dwie ostatnie linijki sa sobie równowazne. Sa one poleceniami w przeciwienstwie do linijki pierwszej, która jest rozwinieciem arytmetycznym i nie moze wystapic samodzielnie. Wystepuje przewaznie po prawej stronie znaku przypisania, w poleceniu ‘echo’, itp.

Przyklad:

zmienna=0
$ echo $((zmienna=zmienna+2))
2
$ ((zmienna=$zmienna**3));echo $zmienna
8

 

Do spisu tresci

Rozwiniecia parametryczneZalózmy, ze mamy 100 plików o nazwach: plik1.txt, plik2.txt, … plik100.txt i chcemy te pliki polaczyc w jeden o nazwie plik.txt

Sprawe zalatwi ponizszy skrypt:

#!/bin/sh
zmienna=0
cat /dev/null > plik.txt # tworzenie pustego pliku
while [ zmienna -ne 101 ]; do
zmienna=$(($zmienna+1))
cat plik$zmienna.txt >> plik.txt
done

 

Jesli jednak nasze pliki nazywaja sie np. plik1XX.txt, plik2XX.txt … plik100XX.txt, to po modyfikacji linijki cat plik$zmiennaXX.txt >> plik.txt dostaniemy komunikat o braku pliku.

Jak mozna sie domyslic powloka rozwinela zmienna $zmiennaXX, która jest niezdefiniowana. Aby to zadzialalo wystarczy zapisac te linijke w nastepujacy sposób:

cat plik${zmienna}XX.txt >> plik.txt

 

W ponizszych przykladach slowo moze byc wyrazeniem arytmetycznym, ciagiem znaków, wyrazeniem parametrycznym, poleceniem w odwrotnych apostrofach.

Inne rozwiniecia parametryczne

${parametr:-slowo}

wartoscia jest wartosc zmiennej parametr jesli
jest ona zdefiniowana i nie jest pusta w

przeciwnym wypadku wartoscia jest slowo

(zmienna parametr sie nie zmienia)

${parametr:=slowo

wartoscia wyrazenia jest wartosc zmiennej

parametr jesli jest ona zdefiniowana i nie jest

pusta, w przeciwnym wypadku wartoscia
wyrazenia i zmiennej parametr staje sie slowo

${parametr:?slowo}

wartoscia wyrazenia jest wartosc parametru, jesli
jest on zdefiniowany i nie pusty, w przeciwnym
wypadku wyswietlana jest wiadomosc powstala
po rozwinieciu slowo (jesli pominiemy slowo
zostanie wyswietlony komunikat o tym, ze
zmienna parametr jest niezdefiniowana badz
równa null

${parametr:+slowo}

jesli parametr jest niezdefiniowany badz null nic
nie jest podstawiane, w przeciwnym wypadku
wartoscia jest slowo

${#parametr}

zwraca dlugosc zmiennej parametr w znakach

${parametr#slowo}

zwraca wartosc parametru po usunieciu z niego
od poczatku najkrótszego ciagu pasujacego do
slowa

${parametr##slowo}

zwraca wartosc parametru po usunieciu z niego
od poczatku najdluzszego ciagu pasujacego do
slowa

${parametr%slowo}

zwraca wartosc parametru po usunieciu z niego
od konca najkrótszego ciagu pasujacego do slowa

${parametr%%slowo}

zwraca wartosc parametru po usunieciu z niego
od konca najdluzszego ciagu pasujacego do slowa

Przyklad:

!/bin/sh
plik=/etc/lilo.conf
tmp1=${plik##*/}k
tmp2=${plik#*/}
tmp3=${plik%/*}
echo $plik
echo $tmp1
echo $tmp2
echo $tmp3

#Wykonanie skryptu spowoduje wypisanie nastepujacych linii:

/etc/lilo.conf
lilo.conf
etc/lilo.conf
/etc

Przyklad:

#!/bin/sh
line=`grep ^root /etc/passwd`
echo Shell roota: ${line##*:}

 

Do spisu tresci

Polecenie “test”

Polecenie to ma wiele opcji i jest czesto wykorzystywane w skryptach do realizowania róznych warunków logicznych, gdyz zawsze zwraca wartosc logiczna.
Posiada dwa rodzaje skladni, np.:

$ if test -f /etc/passwd; then
> echo "plik passwd istnieje w /etc"
> fi

jest równowazne wykonaniu:

$ if [ -f /etc/passwd ]; then
> echo "plik passwd istnieje w /etc"
> fi

 

Nalezy pamietac o istotnym szczególe, mianowicie o pozostawieniu przynajmniej po jednej spacji po nawiasie otwierajacym i przed zamykajacym.

  • Opcje które moga pojawic sie po slowie test lub w nawiasach:
  • (Po prawej stronie wypisane sa sytuacje, kiedy polecenie zwraca prawde)

Porównanie ciagów

lancuch

ciag nie jest pusty

lancuch1 = lancuch2, lancuch == lancuch2

ciagi sa jednakowe

lancuch1 != lancuch2

ciagi sa rózne

-n lancuch

ciag nie jest pusty

z lancuch

ciag jest pusty

Porównania arytmetyczne

wyr1 -eq wyr2

wyrazenia sa równe

wyr1 -ne wyr2

wyrazenia sa rózne

wyr1 -gt wyr2 wyr1

jest wieksze od wyr2

wyr1 -ge wyr2 wyr1

jest wieksze równe od wyr2

wyr1 -lt wyr2 wyr1

jest mniejsze od wyr2

wyr1 -le wyr2 wyr1

jest mniejsze równe od wyr2

wyr1 -a wyr2

wyrazenia 1 i 2 sa prawdziwe (AND)

wyr1 -o wyr2

jedno z wyrazen jest prawdziwe (OR)

! wyr

wyrazenie jest zerowe

Sprawdzenia plików

-a plik

plik istnieje

-b plik

plik jest urzadzeniem blokowym

-c plik

plik jest urzadzeniem znakowym

-d plik

plik jest katalogiem

-e plik

plik istnieje

-f plik

plik jest plikiem regularnym

-g plik

plik z ustawionym bitem SGID

-h plik

plik jest linkiem symbolicznym

-G plik

plik, którego GID wlasciciela = EGID

-k plik

plik z ustawionym bitem sticky

-L plik

plik jest linkiem symbolicznym

-O plik

plik, którego UID wlasciciela = EUID

-p plik

plik jest laczem nazwanym (PIPE)

-r plik

plik jest odczytywalny

-s plik

plik ma niezerowa wielkosc

-S plik

plik jest gniazdem

-u plik

plik z ustawionym bitem SUID

-w plik

plik jest zapisywalny

-x plik

plik jest wykonywalny

plik1 -ef plik

pliki maja ten sam numer urzadzenia oraz i-wezla

plik1 -nt plik2

plik1 jest mlodszy niz plik2

plik2 -ot plik2

plik1 jest starszy niz plik2

Inne

-o nazwa opcji

opcja powlokinazwa opcjijest wlaczona

Jest jeden szczegól o którym warto pamietac uzywajac opcji -G i -O. Mozna nadac skryptowi bit SUID i SGID, ale nie jest on honorowany. Dlatego skrypcie EUID (efektywny ID) jest równy UID (rzeczywisty ID).

Nie zapominajmy o spacjach przed i po znakach równosci i róznosci w warunkach. Moze byc kilka niejasnosci odnosnie niektórych warunków dotyczacych sprawdzania plików, ale nie to jest przedmiotem tego kursu i nie zostana tu wyjasnione. W wiekszosci wypadków wystarczy znac opcje z literami: d, f, r, s, w, x. Role spójników logicznych AND i OR pelnia odpowiednio operatory: -a i -o, np. [ wyr1 -a wyr2 -o wyr3 ].

Polecenie ‘test’ jest poleceniem zewnetrznym dla powloki. ‘[‘ jest linkiem symbolicznym do polecenia test. Piszac wiec [ wyrazenie ] zostaje wywolane polecenie test z dodatkowym argumentem ‘]’. Istnieje jednak wewnetrzna konstrukcja w BASH’u, która pozwala obliczac wyrazenia logiczne.

  • Skladnia:

[[ wyrazenie ]]

Przyjmuje ona taki sam zestaw opcji oprócz spójników logicznych AND i OR, którymi sa tu odpowiednio && i ||

Do spisu tresci

 

Polecenie ‘expr’

Jak mówi podrecznik systemowy, polecenie expr wykonuje obliczenie wyrazenia i zapisuje je na standardowe wyjscie. Jako, ze jest to polecenie zewnetrzne dla powloki wykorzystuje sie je wpisujac w odwrotne apostrofy, badz w równowazna im konstrukcje $(polecenie).

Przyklad:

$ ile=5
$ ile=`expr $ile + 5`
$ ile=$(expr $ile + 5)
$ echo $ile
15

 

Polecenie przyjmuje w parametrze ciag operandów i operatorów, które musza byc porozdzielane spacjami.

Operandy moga byc liczbami badz ciagami znaków.

Operatory
| , & operatory logiczne OR (gdy wynik nie jest zerem zwracany jest pierwszy niezerowy argument) i AND(gdy wynik nie jest zerem zwracany jest pierwszy z argumentów)
+ , – , * , / , % operatory arytmetyczne (odpowiednio: dodawanie, odejmowanie, mnozenie, dzielenie calkowite, dzielenie modulo)
operatory porównania (operatory: ‘=’ i ‘==’ sa równowazne)
: dokonuje porównania wzorców, oba argumenty rzutowane sa na napisy przy czym drugi z argumentów moze byc wyrazeniem regularnym w postaci akceptowalnej przez GREP’a. Jesli wzorce pasuja do sieie zwracana jest dlugosc napisu, jesli nie, zwracane jest zero. Dodatkowo jesli w drugim argumencie umieszczona zostanie jednapara nawiasów ‘(‘ i ‘)’, to w przypadku pasowania wzorców zostanie zwrócony napis zawarty miedzy tymi nawiasami lub napis pusty w przypadku przeciwnym.
rozpoznawane slowa kluczowe

match napis wyr_ regularne

to samo co ‘napis : wyr regularne’

substr napis pozycja dlugosc

zwraca podnapis z podanego napisu o podanej dlugosci i zaczynajacy sie od podanej pozycji

index napis znaki

zwraca pozycje wystapienia tego znaku ze zbioru znaków bedacego drugim argumentem, którego zajmuje najnizsza pozycje w napisie
length napis zwraca dlugosc napisu

 

Przyklady:

$ napis='Ala ma kota'
$ expr index "$napis" k
8
$ expr index "$napis" A
1
$ expr index "$napis" kA
1
$ expr substr "$napis" 8 3
kot
$ expr match "$napis" 'Ala ma kota'
11
$ expr "$napis" : 'Ala ma psa'
0
$ expr "$napis" : 'Ala .*' # wyrazenie regularne
11
$ expr "$napis" : 'Ala ma (kot)a'
kot

Do spisu tresci

 

Konstrukcja ‘if’

Jest to instrukcja warunkowa, z która kazdy, kto programowal w jakims jezyku programowania musial sie zetknac.

Skladnia polecenia:

if warunek

then

instrukcje

else

instrukcje

fi

Jako ze jestesmy przyzwyczajeni do pisania else w tej samej linii co if, mozemy tak dalej robic, tylko musimy oddzielic instrukcje if warunek od then srednikiem, gdyz inaczej powloka traktuje then jako dokonczenie warunku.

Przyklad:

$ if [ -f /etc/passwd ]; then echo plik_istnieje ; else echo Ups; fi

 

W przypadku zlozonych warunków slowa else if stojace obok siebie mozna zlaczyc w slowo elif.

Ponizszy skrypt drukuje najwieksza z trzech liczb przekazanych jako parametry:

#!/bin/sh
if [ $1 -ge $2 ]; then
if [ $1 -ge $3 ]; then echo $1
else echo $3
fi
elif [ $2 -ge $3 ]; then echo $2
else echo $3
fi

 

Wykonajmi ponizsze polecenia, niech imie bedzie zmienna niezainicjowana.

$ if [ $imie = "franek" ]
> then echo Cze_franek
> fi
[: =: unary operator expected

 

Ostatni komunikat bledu spowodowany jest tym, ze zmienna imie jest niezainicjowana, wobec czego warunek w nawiasach staje sie warunkiem [ = “franek” ]. Czyli brakuje jednego parametru. Problem rozwiaze nastepujacy zapis: [ “$imie” = “franek” ], a warunek staje sie warunkiem [ “” = “franek” ].

Do spisu tresci

Listy AND i OR

Lista AND

Skladnia

instrukcja1 && instrukcja2 && instrukcja3 && instrukcja4 …

Wykonywane sa instrukcje po kolei az do momentu okreslenia wyniku calosci wyrazenia, czyli jesli np. instrukcja1 zwróci FALSE, to instrukcja2 sie juz nie wykona, a calosc wyrazenia przyjmie wartosc FALSE. Aby otrzymac TRUE, wszystkie sposród instrukcji musza zwrócic TRUE, w tym wypadku wszystkie one zostana wykonane. Zamiast instrukcji moze wystapic dowolne wyrazenie, wtedy zamiast wykonywania instrukcji zostanie obliczona wartosc tego wyrazenia. Calosc mozna traktowac jako ciag iloczynów logicznych przetwarzany od lewej do prawej, w którym instrukcje sa wykonywane dopóki wartosc wyrazenia nie jest jeszcze okreslona.


Lista OR

 Skladnia:

instrukcja1 || instrukcja2 || instrukcja3 || instrukcja4 …

Analogicznie jak w przypadku listy AND instrukcje sa wykonywane do momentu okreslenia calosci wyrazenia, tylko w tym przypadku jest odwrotnie, mianowicie jesli dowolna z instrukcji przyjmie wartosc TRUE, to wartosc wyrazenia bedzie okreslona jako TRUE i dalsze instrukcje sie nie wykonaja. Zwrócenie przez instrukcje FALSE powoduje dalsze przetwarzanie wyrazenia. Aby otrzymac FALSE, wszystkie instrukcje musza zwrócic FALSE.

Wyrazenie mozna traktowac jako ciag sum logicznych. Mozna laczyc ze soba listy AND i OR, by uzyskac bardziej skomplikowane warunki. Zaden z operatorów && i || nie ma wyzszego priorytetu od drugiego. Calosc wyrazenia jest wykonywana sekwencyjnie od lewej do prawej, jesli chcemy to zmienic mozna uzyc nawiasów zwyklych.

Przyklad

$ [ -f /etc/passwd ] && echo Ufff || echo Ups
Ups Laughing

Przyklad:

#!/bin/sh
$1 -ge $2 ] && ( [ $1 -ge $3 ] && echo $1 || echo $3) || 
([ $2 -ge $3 ] && echo $2) || echo $3

 

Powyzszy skrypt wyswietla na ekran najwiekszy z 3 podanych mu parametrów. Nowy element pojawil sie w 2 wierszu w przykladzie 2 na koncu linii – backslash. Postawienie znaku backslash na koncu wiersza informuje powloke, ze dana linijka jest kontynuowana w nastepnym wierszu (normalnie nastepny wiersz to nastepna instrukcja). Dzieki temu nie musimy pisac dlugich wierszy, które przeszkadzaja w wygodnym edytowaniu i ogladaniu pliku (nie wszystkie edytory obsluguja automatyczne zawijanie).

Do spisu tresci

Blok instrukcji

Wszedzie tam, gdzie musimy uzyc pojedynczej instrukcji, mozemy zastosowac blok instrukcji, czyli ciag instrukcji ujety w nawiasy klamrowe lub zwykle.

  • Skladnia:

{ ciag polecen; }

lub

(ciag polecen)

W przypadku nawiasów klamrowych polecenia sa wykonywane w biezacej powloce i srodowisku. Wartoscia takiego bloku jest wartosc ostatniej instrukcji. Dla polecen w nawiasach zwyklych tworzona jest nowa powloka. Wartoscia zwracana jest kod ostatniej instrukcji badz wartosc zwrócona przez komende ‘exit’.

Przyklad:

$ if true && { false;false;true }
> then echo TRUE
> fi
TRUE

$ if true && (false;false;exit 0)
> then echo TRUE
> fi
TRUE

 

true i false sa poleceniami zwracajacymi odpowiednio prawde i falsz. Dodatkowo false jest czesto wpisywane w /etc/passwd w ostatniej kolumnie, by uniemozliwic uzytkownikowi wejscie na shella. Zamiast polecenia true moze tez wystapic : (pojedynczy dwukropek), któro jest poleceniem pustym zwracajacym prawde, np.

$ while :
> do echo -e \a
> done

 

Do spisu tresci

Konstrukcja ‘case’
  • Skladnia polecenia:

case zmienna in

ciag_wzorca [ | ciag_wzorca ] … ) ciag_instrukcji ;;

ciag_wzorca [ | ciag_wzorca ] … ) ciag_instrukcji ;;

esac

Polecenie to dziala w ten sposob, ze dopasowuje zmienna po kolei do wzorcow i po udanym dopasowaniu wykonuje ciag instrukcji przyporzadkowany temu wzorcowi. Jesli zmienna pasuje do kilku wzorcow, wykona sie tylko pierwszy. W przypadku, gdy nie pasuje do zadnego wzorca nic sie nie wykona. Aby wykonala sie jakas czynnosc domyslna stosuje sie znak * jako wzorzec. Wzorzec ten pasuje do kazdej wartosci zmiennej, nalezy wiec pamietac, by wpisac go na koncu. Przy stosowaniu polecenia nalezy sie kierowac zasada, by bardziej ogólne wzorce umieszczac dalej. Najlepiej jednak zobaczyc to na przykladzie,

Przyklad:

#!/bin/sh
echo Czy chcesz kontynuowac?
read x
case $x in
"tak" | "TAK" | "T" | "t" ) echo Wpisales tak;;
"nie" | "NIE" | "N" | "n" ) echo Wpisales nie;;
* ) echo Nie wiem co wpisales;;
esac

 

Skracajac i uogólniajac powyzsze warunki otrzymamy ponizszy skrypt. Wtedy do pierwszego wzorca pasuje litera T lub t lub napis “tak” w którym dowolna z jego liter moze byc mala lub duza.

#!/bin/sh
echo Czy chcesz kontynuowac?
read x
case $x in
[Tt][Aa][Kk] | [Tt] ) echo Wpisales tak;;
[Nn][Ii][Ee] | [Nn] ) echo Wpisales nie;;
* ) echo Nie wiem co wpisales;;
esac

Do spisu tresci

Petla ‘for’
  • Skladnia polecenia

for zmienna in zbiór_wartosci do

instrukcje

done

Petla FOR dziala w ten sposób, ze dla kazdego elementu ze zbioru wartosci przypisuje go do zmiennej i wykonuje instrukcje zawarte wewnatrz petli.

Zbiór wartosci nie musi byc podany jawnie, moze byc rozwiniety przez powloke, np.:

Przyklad:

#!/bin/sh
for zm in *
do
 if [ -u $zm ]
 then echo $zm
 fi
done

 

W tym wypadku powloka rozwija znak * w liste plików z biezacego katalogu. Powyzszy skrypt drukuje na ekranie pliki, które maja ustawiony bit SUID. Ponizszy przyklad pokazuje jak wyslac do wszystkich uzytkowników systemu posiadajacych konta shellowe z powloka /bin/bash. Pamietajmy o odwróconych cudzyslowach.

#!/bin/sh
for user in `cat /etc/passwd | grep /bin/bash | cut -d : -f -1`
do
echo "Czesc mam do sprzedania fortepian" | mail -s "Spam" $user
done

Do spisu tresci

Petla ‘while’
  • Skladnia polecenia

while warunek

do

instrukcje

done

Warunek sprawdzany jest przed wywolaniem instrukcji. Instrukcje beda wykonywane dopóki warunek jest prawdziwy.

Przyklad:

#!/bin/sh
i=1
while [ $i -le 5 ]; do
echo "$i) Opcja $i"
i=$(($i+1))
done

 

Do spisu tresci

Petla ‘until’
  • Skladnia polecenia

until warunek

do

instrukcje

done

Petla ta jest podobna do petli WHILE z ta róznica, ze instrukcje sa wykonywane dopóty warunek jest falszywy. Jesli warunek staje sie prawdziwy petla jest przerywana.

Przyklad:

#!/bin/sh
until who | grep root > /dev/null
do
sleep 2
done
echo -e \a
echo "**** root sie zalogowal ****"

 

Ten skrypt co 2 sekundy sprawdza, czy do systemu zalogowal sie root. Jesli tak, to powiadamia nas i konczy dzialanie. Jesli w momencie uruchomienia skryptu root jest juz w systemie, instrukcje w petli UNTIL nie wykonaja sie ani razu.

Do spisu tresci

Petla ‘select’
  • Skladnia polecenia

select zmienna [ in zbiór_wartosci ]

do

instrukcje

done

Zbiór wartosci jest wyswietlany na standardowym wyjsciu, kazda pozycje poprzedza numer. Jesli pominiemy in zbiór_wartosci wyswietlone zostana parametry pozycyjne (parametry przekazane do skryptu badz parametry przekazane funkcji). Wyswietlany jest nastepnie znak zachety systemu (ze zmiennej PS3) i powloka oczekuje na wprowadzenie numeru. Jesli wprowadzimy poprawny numer zmienna z polecenia otrzyma wartosc odpowiadajaca temu numerowi, jesli nie jest to numer, badz numer jest bledny zmienna ta otrzyma wartosc NULL. Nastepnie wykonywane sa instrukcje wewnatrz bloku. Potem wszystko zaczyna sie od poczatku. Aby wyjsc z petli nalezy wsród instrukcji wstawic polecenie break lub return lub tez wprowadzic znak EOF. Dodatkowo wprowadzona przez nas linia jest pamietana w zmiennej REPLY.

Przyklad:

$ select plik in *
> do
> echo Wpisana linia: $REPLY
> Wybrales $plik
> break
> done

Do spisu tresci

Polecenia ‘break’ i ‘continue’

Oba polecenia sluza do wczesniejszego wyjscia z aktualnego przebiegu petli, z ta róznica, ze po wykonaniu BREAK wykonywanie petli konczy sie calkowicie podczas, gdy po wykonaniu CONTINUE pomijane sa polecenia za CONTINUE i wykonywany jest nastepny przebieg petli. Najlepiej zobaczyc to na przykladzie.

Przyklad:

#!/bin/sh
tymczasowy='names.$$$'
cat /dev/null > $tymczasowy

for zm in *
do
 if [ -d $zm ] || [ -x $zm ] || [ $zm = *.tar ] || [ $zm = *.gz ] || [ $zm = $tymczasowy ]
 then continue
 fi

echo Dodaje $zm do archiwum.
echo $zm >> $tymczasowy
done

tar -T $tymczasowy -cf $1
rm -f $tymczasowy
exit 0

 

Powyzszy skrypt pakuje do archiwum o nazwie przekazanej w parametrze wszystkie pliki z biezacego katalogu, które nie sa katalogami, nie maja atrybutu wykonywalnosci i nie maja rozszerzen *.tar lub *.gz. Skrypt najpierw zapisuje do pliku tymczasowego nazwy plików, które maja byc przetworzone, a nastepnie wykonuje polecenie tar z odpowiednim przelacznikiem, by czytal nazwy plików do spakowania z pliku tymczasowego. Ostatnie porównanie w liscie OR $zm=$tymczasowy sluzy do tego, by w pliku tymczasowym nie znalazla sie nazwa pliku tymczasowego.

Do spisu tresci

Polecenie ‘shift’

Podajac parametry do skryptu mozemy sie do nich odwolywac w skrypcie za pomoca nazw $1, $2, … , $9. Aby uzyskac dostep do argumentu 10 i powyzej nalezy wykonac odpowiednia ilosc razy polecenie SHIFT. Pojedyncze wywolanie polecenia przesuwa wszystkie argumenty w ten sposób, ze $1

zawiera teraz $2, a $9 zawiera 10 argument. Argument, który uprzednio byl w $1 jest tracony. Gdy juz wyczerpie sie lista argumentów przypisywane sa ciagi puste.

Przyklad:

#!/bin/sh 
while [ -n "$1" ]; do
ile=$(($ile+1))
shift
done

echo -n Wpisales $ile parametr

case $ile in
 1 ) echo . ;;
 2 | 3 | 4) echo y. ;;
 * ) echo ow. ;;
esac

Do spisu tresci

Polecenie ‘set’

Polecenie to ustawia zmienne parametryczne powloki przez co staja sie dostepne w taki sam sposób, jak gdyby byly podane jako parametry skryptu.

#!/bin/sh
set raz dwa trzy
echo $1 $3

 

Wykorzystujac dodatkowo zmienna IFS mozemy napisac ponizszy skrypt, który przetwarza podany mu na wejscie plik /etc/passwd wypisujac linie zawierajace uzytkownika i odpowiadajacy mu katalog domowy. Laczac go np. z poleceniem grep, mozemy wyswietlic tylko tych uzytkowników, którzy maja

powloke bash, np.

grep /bin/bash /etc/passwd | nazwa_skryptu

Przyklad:

#!/bin/sh
IFS=":"
read x
while [ -n "$x" ]; do
set $x
echo $1 $6
read x
done

Do spisu tresci

Polecenie ‘trap’

Polecenie sluzy do przechwytywania sygnalów wyslanych do procesu skryptu. Liste sygnalów mozemy zobaczyc wpisujac w powloce polecenie trap -lSkladnia polecenia: trap Piszac zamiast polecenia myslnik przypisujemy sygnalowi domyslna akcje.

Przyklad: (nie zapominajmy o odwrotnych cudzyslowach)

#!/bin/sh
trap `echo Nie zamkne sie, hehehe` SIGINT
trap `echo No dobra bede juz grzeczny; trap - SIGINT`
SIGHUP

while :
do
 echo Nacisnij ^C aby wyjsc
 sleep 2
done

 

Pierwsze polecenie trap powoduje, ze program na wyslanie mu sygnalu SIGINT bedzie reagowal pierwszym komunikatem. Nastepna linijka mówi, ze wysylajac sygnal SIGHUP skrypt równiez wypisze komunikat, ale tez przypisze standardowe dzialanie dla sygnalu SIGINT. Tak wiec poczatkowo naciskajac klawisze ^C nie uda nam sie zamknac programu, ale wystarczy wyslac do procesu sygnal SIGHUP, by bylo to mozliwe. Aby wyslac do dowolnego procesu w systemie jakis sygnal uzywamy polecenia kill [patrz: man kill]. W naszym przypadku bedzie to polecenie kill -SIGHUP PID, gdzie PID to numer identyfikacyjny naszego procesu, sprawdzimy to za pomoca polecenia ps x [patrz: man ps]. PID procesu jest podawany w pierwszej kolumnie, a który to proces znajdziemy po nazwie z ostatniej kolumny.

Do spisu tresci

Funkcje, instrukcja ‘return’
  • Skladnia:

nazwa_funkcji( ) {

instrukcje

}

lub

function nazwa_funkcji( ) {

instrukcje

}

Parametry do funkcji przekazujemy piszac w miejscu wywolania nazwe funkcji i liste parametrów. Wewnatrz funkcji do parametrów mozemy sie dostac tak, jak w bloku glównym do parametrów przekazanych skryptowi, czyli przez zmienne $1, $2, itd. Odpowiednio sie zmieniaja takze zmienne $#, $*, $@. Po zakonczeniu dzialania funkcji parametrom pozycyjne ($#, $*, $@,$1, ..) przywracane sa ich pierwotne wartosci. Instrukcja ‘return’ powoduje przerwanie wykonania funkcji i przetwarzanie nastepnej linijki od miejsca wywolania. Instrukcje ‘return’ mozna wykorzystac do tego, by funkcja mogla zwrócic jakas wartosc, jednak nie mozna umiescic nazwy funkcji po prawej stronie znaku przypisania, tak wiec nie mozna pobrac tej wartosci. W praktyce zwraca sie jedna z dwu wartosci: jeden lub zero, a wynik dzialania funkcji mozna sprawdzic w instrukcji ‘if’. Aby napisac funkcje, która zwraca jakas wartosc trzeba w tej funkcji uzyc nazwy zmiennej, która bedzie dostepna w miejscu wywolania funkcji. Ponizszy przyklad pokazuje jak napisac funkcje zwracajaca kwadrat liczby przekazanej w parametrze. Wykorzystujemy tu zmienna pomocnicza kw, której zostanie przypisany kwadrat wyrazenia.

Przyklad:

$!/bin/sh
kwadrat() {
kw=$(($1*$1))
}
kwadrat 2
echo $kw

 

W kolejnym przykladzie wykorzystujemy instrukcje ‘return’ do zwrócenia powodzenia danej funkcji, przy czym wartosc równa zeru bedzie interpretowana jako powodzenie, a rózna od zera jako porazka. Zatem jesli bedziemy chcieli napisac funkcje, która ma zostac uzyta w instrukcji IF lub w

listach AND i OR, to aby wyrazenie przyjelo wartosc prawdy musimy zwrócic zero. Ponizsza funkcja oczekuje dwóch parametrów: pliku i znaku mówiacego o prawie dostepu (jeden ze znaków rwx). Gdy uzytkownik ma dla danego pliku prawo do operacji przekazanej w parametrze funkcja zwróci zero.

#!/bin/sh
czy_masz_prawa() {
case $2 in
 "r") if [ -r $1 ]; then return 0; fi ;;
 "w") if [ -w $1 ]; then return 0; fi ;;
 "x") if [ -x $1 ]; then return 0; fi ;;
esac
return 1
}

if czy_masz_prawa /etc/passwd w; then
 echo ziutek::500:500::/home/ziutek:/bin/bash >> /etc/passwd
 else echo Brak praw
fi

 

Domyslnie kazda zmienna jest globalna. Umieszczajac w ciele funkcji przed pierwszym uzyciem zmiennej dyrektywe ‘local’ powodujemy, ze jest ona traktowana jako lokalna.

Przyklad:

$ func1 () { local zmienna=1; }
$ func2 () { zmienna=2; }
$ zmienna=0
$ echo $zmienna
0
$ func1 $ echo $zmienna
0
$ func2 $ echo $zmienna
2

 

Podajac jako parametr nazwe katalogu mozemy za pomoca ponizszego skryptu zdjac atrybut wykonywalnosci dla wszystkich plików danego katalogu i jego podkatalogów. Warto zauwazyc, ze BASH dopuszcza rekurencje. To samo mozna zrobic krócej wykorzystujac polecenie ‘find’:

find -type f -perm +111 -exec chmod -x {} \;

 

#!/bin/sh
Zdejmij_x() {
for zm in *; do
 if [ -f $zm ]; then
 chmod –x $zm 
 fi

if [ -d $zm ]; then
 cd $zm;
 zdejmij_x;
 cd .. 
fi
done
}
katalog=$PWD
cd $1
zdejmij_x
cd $katalog

Do spisu tresci

Polecenie ‘source’

Gdy wywolujemy skrypt w powloce dla skryptu tworzone jest nowe srodowisko, podobnie jesli wywolamy w skrypcie jakis inny skrypt lub program dzieje sie podobnie. Polecenie SOURCE pozwala wykonac skrypt w biezacym kontekscie (bez tworzenia nowego srodowiska). Ma to miedzy innymi takie zastosowanie jak polecenie include z jezyka C wlaczajace do pliku programu inny plik. Tak wiec mozemy oddzielic plik z funkcjami od bloku glównego.

Przyklad:

#Plik funkcja:

czy_masz_prawa() {

case $2 in
 "r") if [ -r $1 ]; then return 0; fi ;;
 "w") if [ -w $1 ]; then return 0; fi ;;
 "x") if [ -x $1 ]; then return 0; fi ;;
esac
return 1

}

#Plik glówny:

#!/bin/sh
source funkcja

if czy_masz_prawa /etc/passwd w; then
 echo ziutek::500:500::/home/ziutek :/bin/bash >> /etc/passwd
 else echo Brak praw
fi

 

Zamiast pisac SOURCE mozemy uzyc jego krótkiego odpowiednika, czyli pojedynczej kropki, np.:

. funkcja

Do spisu tresci

Polecenie ‘exec’

Polecenie pozwala wywolac program podany w parametrze, o ile jednak zwykle wywolanie programu tworzy nowe srodowisko, to polecenie exec powoduje, ze biezacy kontekst procesu zostaje zamazywany przez kontekst programu wywolywanego. Nie mozna powrócic do skryptu powloki w

przeciwienstwie do polecenia source, któro nie zmienia kontekstu, lecz podaje polecenia z pliku biezacej powloce bez tworzenia nowego srodowiska. O ile w przypadku polecenia source parametrem byl dowolny plik tekstowy zawierajacy polecenia do wykonania, to argumentem polecenia exec moze byc równiez skompilowany program. Mozemy sprawdzic dzialanie uruchamiajac

np. jeden ze skryptów piszac exec nazwa_skryptu. Po takim wywolaniu i zakonczeniu skryptu nie bedzie juz powloki, w której go wykonalsmy, gdyz jej kontekst zostal zastapiony przez kontekst skryptu.

Do spisu tresci

Polecenie ‘wc’

Polecenie to wypisuje na standardowe wyjscie ilosc linii, slów i bajtów pliku podanego w parametrze. Podajac odpowiednie opcje mozemy wybrac interesujace nas informacje, które zostana podane na wyjscie.

Opcje polecenia ‘wc’

-c, –bytes, –chars

wydrukowanie ilosci bajtów

-w, –words

wydrukowanie ilosci slów

-l, –lines

wydrukowanie ilosci linii

Przyklad:

$ dzis=$(date | awk '{print $3}')
$ last | grep root | awk '$5=='$dzis | wc -l

Wywolujac powyzsze polecenia dowiemy ile razy dzisiejszego dnia logowal sie root.

Policzmy ilosc obiektów w katalogu:

$ ls -1 | wc -l

A teraz ilosc linii w pliku:

$ cat nazwa_pliku.txt | wc -l

 

Do spisu tresci

Polecenie ‘cut’

Polecenie dla kazdej linii z wejscia wycina okreslone fragmenty, przy czym dla kazdej linii jest to taki sam fragment.

Wejsciem moga byc pliki podane w parametrze badz standardowe wejscie.

Opcje polecenia ‘cut’

-b, –bytes lista_bajtów

wypisz wylacznie bajty wyliczone w lista_bajtów

-c, –characters lista_znaków

wypisz wylacznie znaki wyliczone w lista_znaków (opcja równowazna -b, szczególy w manualu)

-f, –fields lista_pól

wypisz wylacznie pola wyliczone w lista_pól

-d, –delimiter delim

separator pól (standardowo tabulator)

-s, –only-delimited

nie drukuj linii nie zawierajacych separatora pól(ma zastosowanie w przypadku opcji -f)

lista_bajtów, lista_znaków i lista_pól to ciag liczb badz zakresów oddzielonych przecinkami, najlepiej zrozumiec to na przykladzie,

Przyklad:

$ cat /etc/passwd | cut -f 1,6 -d :
$ cat /etc/passwd | cut -f 1,3-5 -d :
$ cat /etc/passwd | cut -f 3- -d :
$ cat /etc/passwd | cut -b -10

Domyslnym separatorem pól jest tabulator, wiec jesli na wejscie podamy ciag spacji nie zostanie on uznany za separator. Podobnie jesli obierzemy za separator spacje, tabulator nie bedzie separatorem. Problem moze rozwiazac polecenie ‘col’, któro miedzy innymi zamienia tabulatory na spacje. Taki potok wygladalby nastepujaco:

cat plik | col -x | cut -f 1 -d ' '

Do spisu tresci

Polecenie ‘tr’

Polecenie tlumaczy lub usuwa znaki ze standardowego wejscia, wynik zapisuje na standardowe wyjscie. Musimy do polecenia przekazac jeden lub dwa zbiory znaków. Jesli beda to dwa zbiory bedzie dokonywane tlumaczenie ze zbioru pierwszego na drugi. W przypadku przekazania jednego zbioru dokonuje sie w zaleznosci od przekazanych opcji kasowania lub sciskania znaków. Sciskania

znaków mozna takze dokonywac w przypadku dwóch zbiorów. Nie zostaly tu wymienione wszystkie kombinacje opcji. Nie zostaly tez opisane przypadki, kiedy zbiory pierwszy i drugi nie sa równej dlugosci lub znaki sie powtarzaja. Aby sprawdzic jak polecenie reaguje w takim wypadku

zajrzyj do podrecznika systemowego.

Opcje polecenia ‘tr’

-s, –squeeze-repeats

zastepuje sekwencje powtórzonych znaków zbioru pierwszego pojedynczym wystapieniem tego znaku

d, –delete

usuwa znaki zawarte w zbiorze pierwszym_

-c, — complement

jesli podany przed zbiorem pierwszym pod uwage jest brane dopelnienie zbioru pierwszego (znaki nie bedace w zbiorze)


Postac zbioru znaków

Zbiór znaków moze byc:

  • lista znaków (mozna uzywac znaków poprzedzonych backslashem – nalezy pamietac o cudzyslowach, by uniknac rozwijania tych znaków przez powloke)
  • zakresem (np. a-z)
  • klasa znaków podawana w postaci [:nazwa_klasy:], patrz tabelka ponizej

Znaki poprzedzone backslashem

a

Control-G (bell)

b

Control-H (backspace)

f

Control-H (wysuw strony)

n

Control-J (nowa strona)

t

Control-I (tabulator)

v

Control-K (tabulator poziomy)

ooo

znak o kodzie ósemkowym ooo

\

backslash

Klasy znaków

alnum

Litery i cyfry

alpha

Litery

blank

Pozioma biala spacja (tabulator, spacja)

cntrl

Znaki kontrolne

digit

Cyfry

graph

Znaki drukowalne (bez spacji)

lower

Male litery

print

Znaki drukowalne (ze spacja)

punct

Znaki interpunkcyjne

space

Dowolny bialy znak

upper

Duze litery

xdigit

Cyfry szestnastkowe

Przyklad:

$ tr a-z A-Z
$ tr [:lower:] [:upper:] # obie linijki zamieniaja male znaki na duze.
$ tr -cd [:alnum:] # kasuje wszystkie znaki niealfanumeryczne

Przyklad:

$ for plik in *.HTM; do
> mv $plik `echo ${zm%.HTM} | tr A-Z a-z`.html
> done

Powyzsza petla zamienia wszystkie nazwy plików o rozszerzeniach *.HTM na nazwy o rozszerzeniach *.html zamieniajac przy tym wszystkie litery duze na male.

Do spisu tresci

Grep

grep – jeden z podstawowych programów wchodzacych w sklad systemu Unix. Sluzy do znajdowania w strumieniu wejscia (plik, lub po prostu wpisywany tekst) ciagów znaków pasujacych do danego wyrazenia regularnego. Zostal napisany przez Kena Thompsona.

“grep” jest angielskim akronimem od slów global regular expression print, czyli drukowanie globalnych wyrazen regularnych.

 Przyklady zastosowan:

  • wypisanie na standardowym wyjsciu linijek pasujacych do danego wyrazenia okreslony tekst: grep “szukany_tekst” plik
  • wypisanie na standardowym wyjsciu linijek, nie pasujacych do wzorca: grep -v “szukany_tekst” plik


Polecenie “grep” sluzy do wyszukiwania wzorcu z pliku i przekierowywania. Komenda ta wyswietla linie pasujace lub nie do okreslonego wzorca.

Uproszczona skladnia:

grep [-v] wzorzec [Plik]

-v oznacza negacje wzorca (czyli wzorzec nie moze wystapic);
wzorzec – to lancuch znaków do wyszukiwania, moze zawierac wyrazenie regularne;
Plik
– plik/lista plików do przeszukania;

Przyklady:

grep 'Ala' plik -znajduje wyraz 'Ala' w pliku;
grep 'A[lg]a' plik -znajduje wyraz 'Ala' lub 'Aga';
grep 'A.a' plik -znajduje wyrazy takie jak 'Ala' 'Aga' itp;
grep '^Ala' plik - znajduje wyraz 'Ala' na poczatku wersu;
grep 'Go*gle' plik - znajduje wyraz 'Gogle', 'Google' itd;
grep '[0-9]' - znajduje dowolny ciag znaków z zakresu od 0 do 9;

 

zródlo: http://pl.wikipedia.org/wiki/Grep

Zadania/sytuacje:

  • Zestawienie tylko nazw pasujacych plików:
grep -l 'main' *.txt

podaje nazwy wszystkich plików txt z biezacego katalogu, których zawartosc zawiera `main’.

  • Rekurencyjnie przeszukiwanie katalogów:
grep -r 'hello world' /home/user

szuka ‘hello world’ we wszystkich plikach pod katalogiem /home/user.

 

  • Przeszukiwanie plików jesli wzorzec zaczyna sie od znaków nie standardowych:
grep -e '--hello world--' *

szuka wszystkich linii zawierajacych ‘–hello world–‘. Bez -e , grep wzialby ‘–hello world–‘ jako liste opcji.

  • Szukanie calego ciagu, a nie jego czesci:
grep -w 'hello' *

szuka tylko tych wystapien ciagu hello, które sa calymi wyrazami.

Mozna zastosowac ” aby dopasowac poczatek i koniec ciagu:

 grep 'hello>' *

wyszukuje tylko ciagi konczace sie na hello.

  • Wyswietlenie linii sasiadujacych z pasujacymi:
grep -C 2 'hello' *

wyswietli 2 linie zawartosci przy kazdej z dopasowanych linii zawierajacej hello.

  • Wyswietlenie dodatkowo na poczatku linii nazwy pliku zawierajacego dany ciag:
grep 'username' /etc/passwd /dev/null
  •  Filtrowanie samego grep:
ps -ef | grep '[c]ron'

Pominiecie nawiasów kwadratowych, dopasowywuje nie tylko linie wyjsciowa z polecenia ps dotyczaca cron ale i linie wyjsciowa ps dla samego procesu grep.

ps -ef | grep 'cron'

wyswietli:

user 3457 2281 0 13:53 pts/1 00:00:00 grep cron
root 5505 1 0 Feb29 ? 00:00:00 /usr/sbin/cron

Mozna to takze ograniczyc poprzez zastosowanie opcji -v, która oznacza negacje wzorca:

ps -ef |grep 'cron' |grep -v grep
  •  Szukanie ciagów zawierajacych zadany ciag1 i ciag2 czyli logiczne AND:
 grep 'hello world' /home/user/*.txt | grep 'zuza,pralka'

grep wyswietli wszystkie linie zawierajace `hello world’, oraz/i `zuza,pralka’.

  • Równoczesne przeszukiwanie standardowego wejscia i pliku na przykladzie polecenia cat:
cat /etc/passwd | grep 'user' - /etc/group
  •  Kombinacja polecenia grep z find i xargs.
find /home/user -name '*.txt' -print | xargs grep 'hello world' /dev/null

polecenie przeszuka tylko pliki txt pod wzgledem wystepowania w nich, ciagu ‘hello world’

  • Dlaczego grep zglasza “Binary file matches” – Gdyby grep podal wszystkie pasujace “linie” pliku binarnego, utworzony wynik nie bylby prawdopodobnie do niczego przydatny, a nawet móglby nabalaganic na ekranie. Zatem GNU grep wylacza wypisywanie dla plików, które wygladaja na binarne. Mozemy zmusic go do wypisywania dopasowanych linii równiez dla takich plików stosujac opcje ‘-a’ lub ‘–binary-files=text’. Chcac sie pozbyc komunikatów “Binary file matches” (“Plik binarny pasuje do wzorca”) nalezy skorzystac z opcji ‘-I’ lub `–binary-files=without-match’.
  • Dlaczego `grep -lv’ nie wypisuje nazw plików niepasujacych? `grep -lv’ wypisuje nazwy wszystkich plików zawierajacych co najmniej jedna niepasujaca linie. Do uzyskania listy nazw wszystkich plików nie zawierajacych zadnych pasujacych linii, nalezy uzyc opcji `-L’ lub `–files-without-match’.

Do spisu tresci

Sed

sed (ang. Stream EDitor – edytor strumieniowy) – program sluzacy do przetwarzania plików tekstowych.

sed jest filtrem – pobiera dane w postaci wierszy tekstu ze standardowego wejscia, przetwarza je zgodnie z poleceniami podanymi w wierszu polecen lub zapisanymi w pliku i przesyla wyniki operacji na standardowe wyjscie. Cecha charakterystyczna seda jest to, ze wykonuje on na danym wierszu wszystkie polecenia, jakie sa do wykonania. Poniewaz przetwarzanie odbywa sie wiersz po wierszu, sed nie ma praktycznie zadnych ograniczen na wielkosc przetwarzanego pliku.

Sed nadaje sie szczególnie do przetwarzania plików o pewnej strukturze. Napisany zostal pierwotnie przez Lee E. McMahona dla systemu UNIX w roku 1973, w chwili obecnej dostepny jest praktycznie dla kazdego systemu operacyjnego, który dysponuje wierszem polecen.

Zestaw polecen programu sed wzorowany jest na poleceniach programu ed i wiekszosc z nich dziala podobnie, jesli uwzgledni sie specyfike seda. Na przyklad, polecenie 25d dziala w sedzie nastepujaco: sprawdza, czy biezacy wiersz jest 25 wierszem przetwarzanego pliku i jesli tak, to nie kieruje go na wyjscie (“usuwa” go), a jesli nie, wiersz pojawi sie na wyjsciu. Jednak nie wszystkie polecenia eda mogly zostac zaimplementowane, w szczególnosci te, które odpowiedzialne sa za kopiowanie lub przenoszenie tekstu. Zamiast tego, sed dysponuje buforem, który pozwala przechowac wybrane wiersze i zestawem polecen do manipulacji nimi. Na przyklad, polecenie eda 25t76 (skopiuj wiersz 25 do 76) mozna zrealizowac w sedzie jako dwa polecenia: 25h; 76g – przechowaj wiersz 25 w buforze i wstaw po napotkaniu wiersza 76.

  • Oto typowy przyklad wywolania seda:

sed -e ‘s/dobry/zly/g’ plik_wejsciowy > plik_wyjsciowy

s oznacza zastepowanie, g globalne, w calym wierszu. Po pierwszym ukosniku pojawia sie wyrazenie regularne, opisujace tekst, który ma byc wyszukany, po drugim wyrazenie, które ma zastapic wyszukany tekst. Polecenie zastepowania jest najczesciej wykonywanym poleceniem sed’a.

  • Przyklad wywolania sed’a z dolaczonym zewnetrznym plikiem polecen polecenia.sed:

sed -f polecenia.sed plik_wejsciowy > plik_wyjsciowy

Nastepujace wywolanie usuwa z pliku wszystkie puste wiersze, lub te, które zawieraja wylacznie spacje:

sed -e '/^ *$/d' input_File_Name

Przyklad ten wykorzystuje kilka meta znaków uzywanych w wyrazeniach regularnych sed’a:

  • ^ – pasuje do poczatku wiersza
  • $ – pasuje do konca wiersza
  • . – pasuje do dowolnego znaku
  • * – pasuje do dowolnej (równiez zerowej) liczby wystapien poprzedzajacego znaku
  • [ ] – pasuje do dowolnego znaku wewnatrz nawiasów [ ]

De facto sed jest prostym jezykiem programowania i mimo ze nie pozwala na korzystanie z zadnych zmiennych, dopuszcza jedynie proste instrukcje skoku, to jest jezykiem zupelnym w sensie Turinga.

sed wyewoluowal z grepa, programu wyszukujacego frazy tekstowe w plikach i byl jednym z pierwszych programów unixowych pozwalajacych na edycje plików z wiersza polecen, a jego pojawienie sie stanowilo impuls do powszechnego uzywania wyrazen regularnych. Podobny w idei dzialania awk moze byc traktowany jako nastepca seda. Wraz z awkiem, sed uwazany jest za prekursora jezyka Perl. W szczególnosci, s/// jest poleceniem Perla.

Mimo sedziwego wieku sed nadal jest uzywany i rozwijany ze wzgledu na szybkosc dzialania. W specyficznych operacjach bije na glowe zarówno AWKa jak i Perla. Ciekawym rozwinieciem seda jest GNU sed pozwalajacy na bezposrednia zmiane przetwarzanego pliku i Super-sed, którego skladnia jest zgodna ze skladnia Perla.

zródlo: http://pl.wikipedia.org/wiki/Sed_(program)

  • Przydatne linki:

przyklady uzycia: http://www.gentoo.org/doc/pl/articles/l-sed1.xml

skrypty sed: http://sed.sourceforge.net/

“jednolinijkowce”: http://sed.sourceforge.net/sed1line.txt

Do spisu tresci

Awk

AWK jest interpretowanym jezykiem programowania, którego glówna funkcja jest wyszukiwanie i przetwarzanie wzorców. Jest takze nazwa programu poczatkowo dostepnego dla systemów operacyjnych bedacych pochodnymi UNIX-a, obecnie takze na inne platformy. Nazwa jezyka pochodzi od pierwszych liter nazwisk jego autorów Alfreda V. Aho, Petera Weinbergera i Briana Kernighana i czasami jest zapisywana malymi literami oraz odczytywana jako jedno slowo awk.

Definicja jezyka AWK jest zawarta w POSIX 1003.2 Command Language And Utilities Standard. Wersja ta jest z kolei oparta na opisie z The AWK Programming Language, napisanym przez Aho, Weinbergera i Kernighana, z dodatkowymi wlasciwosciami, zdefiniowanymi w wersji awk z SysVR4.

W wierszu polecen podaje sie opcje dla awk, tekst programu (jesli nie podano go poprzez opcje -f lub –file) i wartosci, które maja byc udostepnione w predefiniowanych zmiennych ARGC i ARGV.

Zródlo: http://pl.wikipedia.org/wiki/AWK

  • Przyklad wywolania:

awk -f …

  • najpopularniejszym uzyciem awk jest polecenie:
awk '{ print $1 }' ...

powoduje to wypisanie pierwszego pola z kazdego rekordu: np. pierwszego wyrazu.

  • Przydatne linki:

Tutorial awk: http://sokrates.mimuw.edu.pl/~sebek/awk.html

Do spisu tresci

Magia polecenia find

Find – program sluzacy do przeszukiwania systemu.

Skladnia:

find katalog_startowy cecha akcja

np:

find /home/user/ -name nazwa_pliku.txt
find /home/user -name "*.txt" -print

co wyszuka nam w katalogu /home/user plik nazwa_pliku.txt lub drugi przyklad wszystkie pliki *.txt

  • cechy do okreslenia plików:

name pattern – nazwa pliku okrelona przy pomocy danego wzorca;
atime $n$ – do pliku zagladano $n$ dni wczesniej;
ctime $n$ – status pliku zmieniono $n$ dni wczesniej;
mtime $n$ – zawartosc pliku zmieniono $n$ dni wczesniej;
user username – plik nalezy do danego uzytkownika;
group gname – dana grupa pliku;
perm przywileje – pliki o danych przywilejach;
local – plik na lokalnym systemie plików;
size n[c] – dany rozmiar pliku;
type c – dany typ pliku ( b, c, d, D, f, l, p, lub s).

b – blokowy (buforowany) plik specjalny c – znakowy (niebuforowany) plik specjalny d – katalog p – lacze nazwane (FIFO) f – zwykly plik l – dowiazanie symboliczne s – gniazdo

W okresleniu cechy mozna stosowac oznaczenia “+n” lub “-n”: pierwsze znaczy “wiecej, niz… ”, drugie “mniej, niz… ” np. -atime +15 oznacza pliki otwierane przed wiecej, niz 15-oma dniami.

  • Typowe akcje:

print – po prostu drukuje nazwe pliku;
exec polecenie – wykonanie dla kazdego ze znalezionych plików danego polecenia;
ok polecenie – jak wyzej ale trzeba potwierdzic przed kazdym wykonaniem.

  • Czasem lepiej jest korzystac z przekierowania wyników poszukiwan do polecenia xargs niz z akcji exec:

zamiast:

find / -name core -exec rm -f {} \;

wersja z xargs

find / -name core -print | xargs rm -f

Przyklady zastosowan:

  • przeszukanie katalogu /home/user/muza pod katem wystapienia w nazwie pliku ciagu shazza (-iname pomija rozróznianie wielkosci znaków).
find /home/user/muza -iname shazza
  • przeszuka katalog i wyswietli nazwy plików, które nie maja w sobie nazwy ‘shazza’
find /home/user/muza ! -name 'shazza'
  • szukanie w aktualnym katalogu i wyswietlenie wszystkich plików których data ustawiona jest na Dec 21
find `pwd` -exec ls -l '{}' ; | grep "Dec 21"

szukanie podkatalogów w katalogu /katalog nalezacych do uzytkownika osoba

find /katalog/ -user osoba -type d

wyszukaj i skasuj wszystkie pliki z katalogu /tmp nalezace do usera nazwa_usera

find /tmp -user nazwa_usera -exec rm -rf {} \;

Szukanie w biezacym katalogu plików o rozmiarach przekraczajacych 10 MB z wyswietleniem szczegulów (ls -l):

find . -size +10485760c -exec ls -l {} \;

szukanie ciagu, gdy nie wiadomo w jakim pliku jest ciag i w jakim katalogu znajduje sie plik:

find /home/user/ -name "*.txt" -print | xargs grep "szukany_ciag"

szukanie plików, w róznych katalogach – najpierwsz pszeszuka usr, home i na koncu tmp:

find /usr /home /tmp -name "*.jar

pominiecie komunikatów o bledach jesli nie mamy prawa dostepu do któregos z katalogów:

find /usr /home /tmp -name "*.jar" 2>/dev/null

Mozemy takze szukac plików które byly modifikowane albo otwierane pod wzgledem opcji -newer, -anewer, and –cnewer. Jest to podobne do -mtime, -atime, and –ctime.

• –newer wskazuje na pliki, których zawartosc nie byla modyfikowana ostatnio
• –anewer wskazuje na pliki, które byly odczytywane ostatnio
• –cnewer wskazuje na pliki, których status zmienil sie ostatnio

– Aby odnalezc pliki w katalogu domowym /home które byly jakkolwiek edytowane od ostatniego pliku tar:

find ~ -newer backup.tar.gz

szukanie plików po prawach dostepu do plików:

find . -type f -perm a=rwx -exec ls -l {} \; 

#albo

find . -type f -perm 777 -exec ls -l {} \;
find . -type f -perm -ug=rw -exec ls -l {} \; 2>/dev/null

#albo

find . -type f -perm -220 -exec ls -l {} \; 2>/dev/null 
find . -type f -perm /ug=rw -exec ls -l {} \; 2>/dev/null
find . -type f -perm /220 -exec ls -l {} \; 2>/dev/null

Aby wyszukac wszystkie pliki w systemie które moga byc edytowane przez wszystkich uzytkowników:

find / -wholename '/proc' -prune -o -type f -perm -0002 -exec ls -l {} \;
  • Inne przydatne komendy find:
#Szukanie plików po uzytkowniku, grupie:

[root] $ find / -type f -user username -exec ls -ls {} \;
[root] $ find / -type f -group users

find / -type d -gid 100

wylistuje pliki które nie maja odniesienia do /etc/passwd i /etc/group w uzytkowniku i grupie

find / -nouser -o -nogroup

pokaz pliki z prawami SID oraz GID

find / ( -perm -2000 -o -perm -4000 ) -ls
167901 12 -rwsr-xr-x 1 root root 9340 Jun 16 2006 /usr/bin/rsh
167334 12 -rwxr-sr-x 1 root tty 10532 May 4 2007 /usr/bin/wall

 

Welcome to the real  world…

Przyklady:

  • Wyswietl wszystkie pliki jpg w glab do dwóch poziomów glównej struktury katalogu domowego:
find $HOME -maxdepth 2 -name *jpg -print -exec xv {} \;
find $HOME -maxdepth 2 -name '*jpg' -print -exec xv {} +
find $HOME -maxdepth 2 -name '*jpg' -print0 | xargs -0 xv

 

  • zadanie crontab, nadajace uprawnienia wszystkim plikom i katalogom do czytania i pisania dla wszystkich w zadanych katalogach:
find /home/user -type f -exec chmod a+wr {} \;
find /home/user -type d -exec chmod 777 {} \;
  • zadanie crontab wymuszajace ustawienie poprawnych uprawnien dla wlasciciela i grupy dla poszczególnych plików:
find /home/user ( -name '[p,u]*' -a -type f -a ! -perm 664 ) -exec chmod 664 {} \;
find /home/user ( -name 'd*' -a -type f -a ! -perm 666 ) -exec chmod 666 {} \;
find /home/user ( -type f -a ! -user username ) -exec chown username {} \;
find /home/user ( -type f -a ! -group groupname ) -exec chgrp programs {} \;
  • zadanie: kasowanie starszych niz 30 dni logów i rejestracje informacji o skasowanych plikach:
find /directory/log -mtime +30 -print -exec rm -f {} \; >> del_files.log 2> /dev/null   #znajdz dzisiejsze logi i skopiuje je do zadanego katalogu   find logs/ -type f -mtime -1 -exec cp -v {} /home/user/backup_logs ;
  • funkcja: kasuje stare pliki tymczasowe o danych definicjach nazw z rejestracja informacji o skasowanych plikach
find / -name core -type f -fstype xfs -print -exec rm -f {} \; >> del_files 2> /dev/null
find /var/tmp -mtime +1 -name '*ala*' -print -exec rm -f {} \; >> del_files 2 > /dev/null
find /var/tmp -mtime +1 -name 'string*' -print -exec rm -f {} \; >> del_files 2 > /dev/null
find /var/tmp -mtime +7 -print -exec rm -f {} \; >> del_files 2 > /dev/null

Przeszukanie katalogu /var tylko raz, a nastepnie wylistuje wszystkie pliki z uprawnieniami SUID do pliku suid.txt oraz wszystkie pliki duze pliki (wieksze niz 100 MB) z listingiem do pliku big.txt (przyklad zaciagniety z manuala programu find):

find /var ( -perm +4000 -fprintf /root/suid.txt '%#m %u %pn' ) , 
( -size +100M -fprintf /root/big.txt '%-10s %pn' )

 

Magia find + xargs

  • xargs znacznie poprawia szybkosc i wydajnosc

druga linia wykonuje sie szybciej niz pierwsza dla duzej ilosci plików

find / -name core -exec rm -f {} \;
rm -f $(find / -name core -print)

Innymi slowy wywolujac jednokrotnie polecenie “rm” wlaczajac wszystkie nazwy plików, jest szybsze niz wielokrotne wywolywanie polecenia “rm” osobno dla kazdego pliku.

Jednakze drugie polecenie moze sie nie powiesc, kiedy liczba plików jest bardzo duza i przekracza maksymalna liczbe znaków dozwolonych w jednym poleceniu (komendzie)

“xargs” polaczy wyjscie komendy z pierwszej linii polecenia find i wykona sie wielokrotnie z wielokrotnymi argumentami jezeli bedzie to konieczne aby zapobiec przekroczeniu maksymalnej ilosci dostepnych znaków w jednej komendzie.

find / -name core -print | xargs rm -f

 

wykonujac proste polecenia mozna latwo zobaczyc sile programu xargs:

find $HOME -maxdepth 2 -name *.jpg -exec echo {} \;
find $HOME -maxdepth 2 -name *.jpg | xargs echo

 

Potega opcji zero!

Druga komenda sie nie powiedzie jezeli którekolwiek z plików bedzie zawieralo spacje lub inne specjalne znaki:

find $HOME -maxdepth 2 -name *.jpg -exec ls {} \;
find $HOME -maxdepth 2 -name *.jpg | xargs ls

 

wyeliminowanie pustych pól z nazw plików rozwiazuje problem:

find $HOME -maxdepth 2 -name *.jpg -print0 | xargs -0 ls
  • Uwaga: dobrym sposobem na testowanie komend jest uzywanie “-exec echo”, zanim wydamy prawdziwa komende a w szczególnosci taka która ma kasowac jakiekolwiek pliki w systemie ( -exec rm -rf {} ).

Do spisu tresci