Sunteți pe pagina 1din 12

SISTEMUL DE OPERARE LINUX (continuare)

Controlul secvential

cda1 && cda2 are semnificaia:
- se execut cda1;
- dac execuia acesteia s-a terminat cu succes (cod de retur zero), se execut i cda2.
cda1 || cda2 are semnificaia:
- se execut cda1;
- dac execuia acesteia se termin cu eec (cod de retur nenul) se execut i cda2.
Exemplu. Dac se tasteaz:
$cd /home/so && ls -l
Se afieaz coninutul directorului /home/so, numai dac acesta exist (comanda cd s-a
terminat cu succes).
Exemplu. Dac se tasteaz:
$cd /home/so || echo Director inexistent
Se afieaz mesajul Director inexistent numai dac directorului /home/so nu exist
(comanda cd s-a terminat cu eec).
Caracterul ; separ dou comenzi care se vor executa succesiv. Delimitatorul de comenzi
permite scrierea mai multor comenzi pe aceeai linie. Trecerea la execuia comenzii urmtoare se
face numai dup terminarea execuiei comenzii precedente din aceeai linie.
Astfel, ntr-o linie de forma: cmd1; cmd2; cmd3 execuia comenzii cmd2 ncepe numai
dup terminarea lui cmd1, iar a lui cmd3 numai dup terminarea lui cmd2.
Exemplu.
$pwd;ls;cd ../ilflorea;pwd;ls >/tmp/iesiri.out
Redirectarea final se aplic numai ultimei comenzi ls. Ieirile celorlalte comenzi apar
pe ecran (nu sunt redirectate).
Observaie. Trebuie fcut deosebirea ntre aceast construcie i legarea n pipe; prin
legare n pipe, pot fi lansate simultan n execuie, n procese separate, mai multe comenzi.
Gruparea comenzilor
O succesiune de comenzi delimitat de paranteze sau de acolade i separate prin ;
conteaz sintactic ca o singur comand. Efectul execuiei unei astfel de comenzi este diferit n
funcie de delimitatorii folosii. Astfel, comenzile dintre paranteze nu afecteaz mediul exterior,
pe cnd cele dintre acolade modific acest mediu.
Exemplu.
${ pwd;ls;cd ilflorea;pwd;ls; } >/tmp/iesiri.out
Redirectarea se va aplica ieirilor tuturor comenzilor grupate.
Pentru:
$( pwd;ls;cd ilflorea; pwd; ls ) >/tmp/iesiri.out
Aplicarea redirectrii va afecta numai in interiorul grupului.

Exemplu.
$( pwd;ls |grep fis) | wc
are ca efect faptul c pentru comanda wc fiierul de intrare este constituit din: fiierul de
ieire produs de pwd la care se adaug rezultatul legrii n pipe ls| grep.
Aceeai efect se obine prin:
$pwd >/tmp/tmp$$; ls | grep >>/tmp/tmp$$
$wc /tmp/tmp$$
Exemplu.
Presupunem c directorul curent este /home/so. Execuia comenzii:
$ pwd; ( cd ..; pwd; ); pwd are ca efect afiarea urmtoarelor linii:
/home/so
/home
/home/so
n schimb, comanda:
$pwd; { cd ..; pwd; }; pwd va afia:
/home/so
/home
/home
n cazul gruprii comenzilor cd i pwd ntre paranteze rotunde, acestea au efect doar n
interiorul lor, n timp ce n cazul gruprii comenzilor ntre acolade, rezultatul execuiei
lor este global, fiind vizibil i n exteriorul grupului.

Conditii sub Linux

Linux recunoate urmtoarele condiii elementare:
a) comparaii numerice;
b) teste asupra irurilor de caractere;
c) teste asupra fiierelor.

Aceste condiii elementare pot fi legate ntre ele prin operatorii:
-a joac rolul de SI logic (AND);
-o joac rolul de SAU logic (OR);
! este operatorul unar de negare (NOT).
Pentru gruparea unor subexpresii se folosesc construcii de forma ( ... ). Deoarece
parantezele sunt caractere speciale, ele trebuie scrise sub una din formele: " ( " , ( , \ pentru
paranteze deschise, respectiv formele " ) " , ) , \ ) pentru parantezele nchise.

Comparaii numerice. Dou expresii numerice pot fi comparate folosind operatorii
relaionali: -lt -le -eq -ne -ge -gt, care corespund operatorilor relaionali din C: < <= ==
!= >= >

Testele asupra irurilor de caractere sunt:
-z ir verific dac irul are lungimea zero;
-n ir verific dac irul are lungime nenul;
s1 = s2 verific dac cele dou iruri sunt egale (unele sisteme de operare accept i
construcia ==);
s1 != s2 verific dac cele dou iruri sunt diferite.

Testele asupra fiierelor sunt:
-e fis verific dac fiierul fis exist;
-s fis verific dac fiierul fis exist i are lungimea nenul;
-r fis verific dac fiierul fis exist i din el se poate citi;
-w fis verific dac fiierul fis exist i n el se poate scrie;
-x fis verific dac fiierul fis exist i este executabil;
-f fis verific dac fiierul fis exist i este un fiier obinuit;
-d fis verific dac fiierul fis exist i este un director;
-L fis verific dac fiierul fis exist i este o legtur simbolic;
-p fis verific dac fiierul fis exist i este un pipe;
-c fis verific dac fiierul fis exist i este un fiier special de tip caracter;
-b fis verific dac fiierul fis exist i este un fiier special de tip bloc.

Testarea unei condiii se face cu comanda test conditie sau [ conditie ]
Dupa executia unei comnenzi, se trimite un cod de retur (sau cod de eroare). De obicei
acesta este zero dac execuia comenzii s-a ncheiat normal i are o valoare nenul n caz contrar.
Comanda test primete ca argument o conditie pe care o evalueaz. n funcie de rezultatul
acestei evaluri, se fixeaz valoarea codului de retur. n cazul n care condiia este adevrat,
codul de retur este fixat la valoarea zero, altfel (condiie fals) codul de retur este fixat la o
valoare nenul. Comanda este utilizata mpreun cu structurile de control shell.

Structuri alternative

Structura alternativ if are o sintax de forma:
if listaCom
then listaCom
[elif listaCom
then listaCom
--------------------
elif listaCom
then listaCom]
[else listaCom]
fi
Lista de comenzi care urmeaz dup if, ca i listele de comenzi care urmeaz dup elif au
un dublu rol: de execuie a comenzilor din list i de fixare a valorii de adevr a execuiei. O
execuie are valoarea TRUE dac codul de retur al ultimei execuii din lista de comenzi are
valoarea zero. Execuia are valoarea FALSE dac codul de retur are valoare nenul. Listele de
comenzi de dup then, ca i lista de comenzi de dup else au doar valori de execuie.

Succesiunea de evenimente care au loc la ntlnirea unei comenzi if este urmtoarea:
- Se execut lista de comenzi ce urmeaz dup if. Dac rezulta valoarea TRUE (condiia
if este adevrat), atunci se execut lista de comenzi de dup then i execuia lui if se termin (se
trece la instruciunea care urmeaz dup fi). n caz contrar (lista de comenzi de dup if genereaz
FALSE) se trece la pasul urmtor.
- Dac exist (una sau mai multe) construcii elif, atunci se execut, pe rnd, listele de
comenzi care urmeaz dup elif, pn cnd una dintre ele genereaz valoarea TRUE. Apoi se
execut lista de comenzi de dup then - ul corespunztor i execuia lui if se termin. n caz
contrar (fie nu exist elif, fie toate listele de comenzi de dup elif - uri au generat FALSE) se
execut pasul urmtor.
- Dac exist else atunci se execut lista de comenzi de dup else i execuia lui if se
termin. n caz contrar (nu exist else), execuia lui if se termin i se trece la execuia comenzii
ce urmeaz dup fi.

Exemplu. Se testeaza daca un fiier este obinuit sau director.
If [ -f ] $1
then echo $1 este un fiier ordinar
elif [ -d ] $1 then echo $1 este un director
else echo $1 este necunoscut
fi

Exemplu. Scriptul urmator:
if grep Ionel" fis_lista > /dev/null
then echo "Numele a fost gasit in lista"
else echo "Numele nu este in lista"
fi
caut numele Ionel in fisierul fis_lista i afiseaz un mesaj n care se precizeaz rezultatul
cautarii. Se folosete redirectarea iesirii ( >/dev/null), pentru ca nu ne intereseaza liniile gsite, ci
doar dac exist asemenea linii. n acest exemplu if testeaz o comand.

Exemplu. Vom rescrie scriptul precedent astfel nct ablonul i fiierul n care cutm
vor fi date ca argumente n linia de comand.
if grep "$1" "$2" >/dev/null
then echo "$1 apare in fisierul $2"
else echo "$1 nu apare in fisierul $2"
fi

Exemplu. Rescriem scriptul precedent, testnd corectitudinea liniei de comand (se
verific dac numrul argumentelor din linia de comanda este corect).
if [ $# -lt 2 ]
then
echo "Prea putini parametri"
exit 1
fi
if grep "$1" "$2" >/dev/null
then echo "$1 apare in fisierul $2"
else echo "$1 nu apare in fisierul $2"
fi
exit 0

Exemple. Testarea de ctre if a altor comenzi.
# If testeaza comanda de comparare a doua fisiere
if cmp a b &> /dev/null # anularea iesirii
then echo "Fisierele a si b sunt identice"
else echo " Fisierele a si b sunt diferite"
fi
# If testeaza comanda de cautare intr-un fisier.
if grep q Bash file
then echo "Fis. contine cel put. o ap. a lui Bash."
fi
# If testeaza legarea in pipe a doua comenzi
word=Linux
Secv_Lit=inu
if echo "$word" | grep q "$Secv_Lit"
then echo "$Secv_Lit gasita in $word"
else echo "$Secv_Lit negasita in $word"
fi

Exemplu. Un fiier de comenzi care afieaz liniile ordonate alfabetic ale unui fiier
text. Numele fiierului va fi dat ca prim argument al linei de comand. O prim variant este:
if [ $# -eq 0 ]
then echo "Trebuie dat un nume de fisier"
else sort $1 | more
fi
#Varianta urmtoare testeaz i tipul fiierului.
if [ $# -eq 0 ]
then echo "Trebuie dat un nume de fisier"
elif [ ! \( -r $1 \) ]
then echo "Fisierul $1 nu exista"
else sort $1 | more
fi


Exemple. Utilizarea codului de retur al comenzii anterioare (coninut n variabila $? ) .
$grep -q cuvant fisier
$if [ $? -eq 0 ];then echo Da;else echo Nu;fi

n comanda grep se folosete opiunea q, prin care nu se afieaz rezultatul cutrii.
Secventa anterioar are acelai efect cu:
$ grep cuvant fisier >/dev/null
$ if [ $? -eq 0 ];then echo Da;else echo Nu;fi

n exemplul urmtor, se face tergerea numai dac comanda cd s-a executat cu succes.
cd mytmp
if (( $? )); then rm * ; fi

Se obine acelai lucru dac se lanseaz:
$cd mytmp && rm *

Exemplu. Un fiier de comenzi care compar directorul curent cu directorul dat ca
parametru n linia de comand.
dirc=`ls l`
dirp=`ls -l $1`
if [ "$dirc" = "$dirp" ]
then echo directoarele `pwd` si $1 coincid
else echo directoarele `pwd` si $1 sunt dif.
fi
Cele dou variabile (dirc, dirp) primesc ca valoare un ir de caractere, reprezentnd
rezumatul unui director (comanda ls). Cnd se face comparaia (condiia din if), este necesar
prezena ghilimelelor, pentru ca fiecare variabil s fie un singur ir de caractere.
Dac se ruleaz exemplul fr ghilimele, rezultatul va fi se afieaz un mesaj de eroare.

Structura alternativ case are sintaxa:
case $var in
list_valori1 ) actiune1;;
list_valori2 ) actiune2;;
...
* ) actiune_implicita;;
esac
Valoarea variabilei var (discriminant pentru case) se compar pe rnd cu valorile
specificate n list_valori1, list_valori2 etc. n momentul identificrii unei corespondene, se
execut aciunea asociat i execuia lui case se termin. Dac valoarea variabilei nu corespunde
cu nici o valoare din liste, se execut aciunea asociat lui * (aciunea implicit), care se afl pe
ultima poziie. Valorile specificate ntr-o list de valori se separ prin | i pot fi exprimate i ca
expresii regulate.
Exemplu. Testarea existenei de fiiere i adugare la sfritul unui fiier.
case $# in
1) if [ -w $1] then cat >> $1;;
2) if [ \( -w $2 \) -a \( -r $2 \)] then cat >> $2 <$1;;
*) echo Fisier inexistent;;
esac
Variabila de mediu # indic numrul de parametri din linia de comand. Dac exist un
singur parametru, coninutul fiierului standard de intrare se adaug la sfritul fiierului al crui
nume este dat prin acest parametru. Pentru doi parametri n linia de comand, coninutul
fiierului indicat de primul parametru este adugat la sfritul fiierului indicat prin al doilea
parametru. Pentru alte situaii se emite un mesaj de utilizare.

Exemplu. Urmtorul script:
case $LOGNAME in
root) PS1="#";;
ilflorea | i.florea ) PS1="utiliz priv $LOGNAME $";;
* ) PS1="User obisnuit \h:\w\$ ";;
esac
export PS1
readonly PS1
poate fi introdus n fiierul /etc/profile pentru a stabili forma prompterului pentru fiecare
categorie de utilizatori. $LOGNAME conine numele ultimului utilizator care s-a conectat la
sistem. Utilizatorii ilflorea i i.florea au un prompter diferit de cel al utilizatorilor obinuii.

Exemplu. O generalizare a comenzii cal. Comanda cal primete ca parametri anul sau
luna n form numeric i afieaz calendarul lunii/anului respectiv/e. n cele ce urmeaz, este
prezentat un script care extinde comanda cal, n sensul c argumentele comenzii pot fi date i n
alte formate. Dac numele cu care este salvat scriptul este calendar, poate fi lansat:
$./calendar ianuarie 2010
$./calendar febr
$./calendar Decem 2010
Coninutul scriptului este:
case $# in
0 ) set `date`; m=$2;y=$6 ;; #cazul fara arg.
1 ) m=$1;set `date`;y =$6 ;;#luna este singurul arg.
2 ) m=$1; y =$2 ;; #se specifica luna si anul
esac
case $m in
Ian*|ian*|Jan*|jan* ) m=1 ;;
Feb*|feb*|Fev*|fev* ) m=2 ;;
Mar*|mar*) m=3 ;;
Apr*|apr*|Avr*|avr* ) m=4 ;;
Mai|mai ) m=5 ;;
Iun*|iun*|Jun*|jun* ) m=6 ;;
Iul*|iul*|Jul*|jul* ) m=7 ;;
Aug*|aug*|Avg*|avg* ) m=8 ;;
Sep*|sep*|Sec*|sec* ) m=9 ;;
Oct*|oct* ) m=10 ;;
Noi*|noi*|Nov*|nov* ) m=11 ;;
Dec*|dec* ) m=12 ;;
[1-9]|10|11|12) ;; #luna se specifica numeric
*) m= ;; #anul se specifica explicit.
esac
/usr/bin/cal $m $y #apel cal

Structuri de ciclare

Structura de ciclere for permite execuia ciclic a unei liste de comenzi, modificnd la
fiecare parcurgere a ciclului valoarea unei variabile specificate n for; are sintaxa de forma:
for variabila [in list_valori]
do
lista_de_comenzi
done
Dac partea opional lipsete, variabila ia pe rnd ca valori argumentele prezente n linia
de comand.

Exemplu. O structur for pentru crearea unui numr oarecare de fiiere.
for i do cat >$i; done
Se observ lipsa prii opionale i c se poate scrie cuvntul rezervat done, n aceeai
linie cu o comand, dac se folosete separatorul ';'.

Exemplu. Afiarea numelor fiierelor din catalogul curent (cu excepia celor ascunse).
for i in *
do
echo $i
done

Exemplu. Sortarea i afisarea coninutului tuturor fiierelor date ca argumente n linia de
comand.
for fis in *
do
sort $fis | more
done
Dac numele scriptului este sortare i se tasteaz: $ sortare fis1 fis2 fis3 se execut
comenzile:
sort fis1 | more
sort fis2 | more
sort fis3 | more

Exemplu. Sortarea i afiarea tuturor fiierelor din directorul curent, al cror nume
contine caracterele fis.
for fisier in *fis*;do;sort fisier |more; done

Observatie: bash recunoate o sintax mprumutat din limbajul C:
max=LimitaSup
for ((i=1; i <= max ; i++))
do
<secventa>
done

Exemplu.
max=10
for ((i=1; i<= max ; i++))
do
echo -n $i...
done
echo
Cnd se lanseaz n execuie, se afieaz.:
1...2...3...4...5...6...7...8...9...10...

Structurile de ciclare while i until

Structura while are sintaxa:
while list_comanda_1
do
list_comanda_2
done
Valoarea testat de comanda while este codul de retur al ultimei comenzi din
list_comanda_1. Dac acesta este 0, se execut list_comanda_2, dup care se reia execuia lui
list_comanda_1 s.a.m.d. Dac s-a returnat o valoare diferit de zero, ciclul se termin.

Structura de ciclare until are sintaxa:
until list_comanda_1
do
list_comanda_2
done
Semantica structurii until este asemntoare cu cea a structurii while; condiia de
terminare a ciclrii n cazul structurii until este invers fa de while .

Comanda shift are ca efect eliminarea primului argument din linia de comand i
deplasarea spre stnga a argumentelor rmase: $2 devine $1 etc.

Exemplu. Afiarea parametrilor din linia de comand:
while [ $# -gt 0 ]
do
echo $1
shift
done
Se utilizeaz variabila de mediu #. Prin shift-are, numrul de parametri se decrementeaz.
Presupunnd c scriptul prezentat anterior are numele ListFis, dac se tasteaz:
$ListFis *
efectul va fi acelai cu cel al comenzii:
$ls
adic afiarea numelor fiierelor din catalogul curent.

Exemplu. Sortarea unui numr oarecare de fiiere specificate n linia de comand; se
verific i dac argumentul dat este un fiier.
while [ $# -gt 0 ]
do
if [ -s $1 ]
then sort $1 | more
else echo $1 nu exista
fi
shift
done

Acelai lucru se poate realiza folosind structura until.
until [ $# -eq 0 ]
do
if [-s $1 ]
then sort $1 | more
else echo $1 nu exista
fi
shift
done

Comanda read citete cte o linie din fiierul standard de intrare i atribuie cuvintele
introduse unor variabile de mediu.
Are sintaxa: read [-r] [Lista_nume]
Cuvintele din linia citit se atribuie pe rnd variabilelor din Lista_nume. Dac numrul de
cuvinte din linie este mai mare dect numrul de variabile, valoarea primit de ultima variabil
cuprinde toate cuvintele rmase. Dac este prezent opiunea -r, backslash se consider parte din
linie. n felul acesta pot fi specificate valori pe mai multe linii (caracterul '\' nu va face parte din
nici o valoare). n caz c lista de nume lipsete, cuvintele citite se atribuie variabilei predefinite
REPLY. Execuia comenzii read returneaz codul 0, cu excepia cazului cnd se ajunge la
sfritul fiierului standard de intrare.
Exemplu. O procedur shell de creare a unei agende telefonice
while read nume pren tel
do
echo -n $nume '' '' $pren '' '' $tel >>agenda
done
cat agenda

Comanda break [n]. Dac argumentul n lipsete, are ca efect ieirea dintr-o structur de
ciclare (for, while sau until); codul de retur este 0, cu excepia cazului cnd shell-ul nu execut
un ciclu n momentul ntlnirii unui break. Dac argumentul n este prezent, el reprezint numrul
de cicluri imbricate din care se iese. Dac argumentul n este mai mare dect nivelul de imbricare,
se prsete ciclul cel mai din exterior.
Comanda continue [n]. Dac argumentul n lipsete are ca efect trecerea la iteraia
urmtoare a unei structuri de ciclare. Dac argumentul n este prezent, se trece la iteraia
urmtoare a unui ciclu exterior celui n care apare comanda.

Exemplu. Ieirea dintr-o structur interioar.
for (( a = 1; a 4; a++ ))
do
echo "Structura exterioara: $a"
for (( b = 1; b 100; b++ ))
do
if [ $b -eq 5 ]
then break
fi
echo " Structura interioara: $b"
done
done

Exemplu. Ieirea din ambele structuri de ciclare.
for (( a = 1; a 4; a++ ))
do
echo " Structura exterioara: $a"
for (( b = 1; b 100; b++ ))
do
if [ $b -gt 4 ]
then
break 2
fi
echo " Structura interioara: $b"
done
done

Exemplu. Trecerea la iteraia urmtoare.
for (( var1 = 1; var1 15; var1++ ))
do
if [ $var1 -gt 5 ] && [ $var1 -lt 10 ]
then
continue
fi
echo "Numar Iteratie: $var1"
done

Exemplu. Utilizarea comenzii continue mpreun cu structurile for i while.
var1=0
while echo " Iteratia lui while: $var1"
[ $var1 -lt 15 ]
do
if [ $var1 -gt 5 ] && [ $var1 -lt 10 ]
then
continue
fi
echo " Numar de iteratie din interior: $var1"
var1=$[ $var1 + 1 ]
done

Exemplu. Trecerea peste 2 iteraii.
for (( a = 1; a = 5; a++ ))
do
echo "Iteratia $a:"
for (( b = 1; b 3; b++ ))
do
if [ $a -gt 2 ] && [ $a -lt 4 ]
then
continue 2
fi
var3=$[ $a * $b ]
echo " Rezultatul lui $a * $b este $var3"
done
done