DERS 8:
7. Kabuk Programlamaya Giriş
Her kabuğun kendine özgü programlama dili yapısı vardır. Bash kabuğu ise güçlü programlama özellikleriyle karmaşık programların rahatça yazılmasına izin verir. Mantıksal operatörler, döngüler, değişkenler ve modern programlama dillerinde bulunan pek çok özellik bash kabuğunda da vardır ve işleyiş tarzları da hemen hemen aynıdır.
Genellikle, bir programı oluşturacak olan komutlar bir dosyaya yazılırlar ve ardından bu dosya çalıştırılır. Herhangi bir editör yardımıyla yazılan program, daha sonra kabuk altında çalıştırılır. Bir kabuk programı diğerlerini çalıştırabilir. Bu düzende kabuk programlarını daha karmaşık komutların bir araya gelmiş ve büyümüş haline benzetebiliriz.
7.1 Kabuk Programları
Kabuk programları, bir veya birden fazla linux komutunu tutan dosyalardır. Bu dosya yaratıldıktan sonra doğrudan dosyanın ismi girilerek veya dosya isminden önce '.' karakteri getirerek çalıştırılabilir. Bir kabuk programı, çalıştırma bitini 1 yapmak suretiyle
"çalıştırılabilir" hale getirilir. chmod komutu yardımıyla bir programı çalıştırılabilir yapmak için ,
$ chmod +x komutismi
yazılabilir. Bundan sonra programın ismi yazılıp enter tuşuna basıldığı zaman bir program Linux komutuymuş gibi çalışacaktır.
$ cat calistir echo -n "Tarih : "
date
$ chmod +x calistir
$ calistir
Tarih : Sun Dec 8 07:11:51 EET 1996
Yukarıdaki örnekte "calistir" isimli iki satırlık bir kabuk programının önce içeriği ekrana yazıldı, ardından çalıştırılacak duruma getirildi ve çalıştırıldı.
Kabuk programları yazarken dosyanın işlevini ve her satırdaki komutun veya komut kümesinin ne amaçla kullanıldığını gösteren açıklama satırları kullanmak işe yarar. Bir açıklama eklemek için satır başına (veya boş satıra) # işareti eklenir ve ardından istenilen cümle girilir. # işaretinden sonraki tüm satır kabuk tarafından gözardı edilir. Aşağıdaki programda komut öncesinde yeralan açıklama satırı, komut hakkında bilgi veriyor.
# gunzip komutu dosya acmak icin kullanilir.
gunzip sistem.gz
Yorum satırı, komutun sonuna da eklenebilir.
ps -aux # sistem surecleri hakkinda ayrintili bilgi..
Bir kabuk altında çalışırken başka bir kabuk için yazılmış bir programı çalıştırmak mümkündür. Örneğin tcsh altındasınız ve daha evvel bash kullanarak yazdığınız bir programı çalıştırmak istiyorsunuz. Önce bash yazarak kabuk değiştirmeli, ardından programı çalıştırmalı, ve tekrar tcsh'a dönmelisiniz. Tüm bunları otomatik olarak yaptırabilirsiniz.
Programın en başına #! karakterini, ardından programın çalışacağı kabuğun patikasını yazın.
Örneğin #!/bin/bash komutunu programın en üstüne eklerseniz bu program bash kabuğu altında çalışacaktır.
7.2 Değişkenlerin Kullanımı
Bir değişkene değer atandığı anda sistem tarafından tanınır. Değişkenler alfabetik veya nümerik karakterlerden oluşabilirler fakat bir değişken sayısal bir değer ile başlayamaz.
Bunların dışında değişken isminin içinde "_" karakteri de bulunabilir. Bir değişkene değer ataması "=" işareti yardımıyla yapılır.
$ mesaj="aksama yemege geliyorum"
İçeriği olan bir değişkene başına "$" işareti konularak ulaşılır. Aşağıda, echo komutu yardımıyla bir değişkenin içeriği ekrana basılıyor.
$ echo $mesaj
aksama yemege geliyorum
$ echo yarin $mesaj
yarin aksama yemege geliyorum
Aynı mesajı değişken kullanmadan da görüntüleyebiliriz:
$ echo "Aksama yemege geliyorum"
Aksama yemege geliyorum
7.3 Giriş/Çıkış İşlemleri
Bir kabuk programı çalışırken kullanıcıdan klavye yardımıyla bilgi girmesi sağlanabilir. Bu tür işlemler için tanımlanan read komutu klavyeyi okur ve aldığı bilgiyi bir değişkene atar.
Aşağıdaki komutları içeren program yardımıyla klavyeden okunan değer ekrana yazılıyor.
echo komutundan sonra birden fazla değişken grubu veya hem değişken, hem de dizi kullanılabilir.
echo Bir sayi giriniz..
read sayi
echo Girilen sayi : $sayi
Bazı durumlarda girilen değer özel karakterleri içerebilir. Bu durumda istenmeyen bazı sonuçların doğması kaçınılmaz olur. Aşağıdaki örneği bir dosya içine yazın ve dosyayı çalıştırdıktan sonra "*" tuşuna basın.
echo Bir karakter giriniz read a
echo Girdiginiz karakter : $a
echo komutunda –n opsiyonu sizi alt satıra geçirmeden bilgi girişi/çıkışı yapmanızı sağlar.
$ echo –n “Adınızı Giriniz:”
echo komutu içerisine değişken koymak mümkündür. Aşağıdaki örnekte $HOME klasörünüz ve tty komutu kabuk tarafından değerlendirilmiştir.
$ echo –e “\007 Ev dizininiz $HOME dur, Şu an ’tty’ ya bağlısınız.”
Boş satır bırakmak için \n yeni satır komutunu kullanabilirsiniz, echo komutuna aynı zamanda tab ifadeside konulabilir. Sadece \ koymayı unutmamak gerekir.
echo “Bu yeni üç satır oluşturur \n\n\n”
echo ”OK”
$ echo –e “İşte ilk tab\tve işte ikinci tab\t\ttamammı!”
Bash da veri girmenin bir yoluda read komutudur.
$ read name surname Serdar Mustafa Celebi
$ echo $name Serdar
$ echo $surname Mustafa Celebi
Bununla ilgili bir kabuk programı aşağıdaki gibi yazılabilir:
# !/bin/sh
# var_test
echo –n “First Name:”
read name
echo –n “Middle Name:”
read middle
echo –n “Last Name:”
read surname
Yukarıdaki programı okunanları görüntüleyecek şekilde düzenleyiniz!.
Çoğu zaman komutlar işleme konulduğunda, o komutun başarı ile gerçekleştirildiğini veya başarısız olduğunu bilmemiz gerekir ki bu komuta bağlı diğer komutun/komutların hangi şekilde devreye gireceğini bilelim.
Komut 1 && Komut 2
&& işaretinin solundaki Komut 1 başarı ile çalıştırıldığında (true değerini alır) sağ taraftaki Komut 2 çalıştırılmaya başlanır.
$ cp myfile.doc myfile.txt && echo “Eğer bu mesajı görüyorsanız cp komutu doğru çalışmıştır”
$ mv /apps/bin /apps/dev/bin && rm –r /apps/bin
Komut 1 || Komut 2
Bu komutta durum ters çalışır. Şöyleki, eğer Komut 1 çalışmadığında Komut 2 devreye girer.
$ cp myfile.doc myfile.txt || echo “Eğer bu mesajı görüyorsanız cp komutu doğru çalışmamıştır”
Eğer birden fazla komutu grup olarak bir defada çalıştırmak istiyorsak, kabuk bize bunu iki metod ile yapmamızı mümkün kılar. Bu komut grubu ya mevcut kabuk üzerinde çalışır yada alt kabuk da çalıştırılır. Mevcut kabuk üzerinde bir grup komutu çalıştırmak istediğimizde her komutu birbirinden ; işareti ile ayırıp, ( ) içerisine almak gerekir.
(Komut 1 ; Komut 2 ; . . .) Bir komutu alt kabukta çalıştırmak istediğimizde,
{Komut 1 ; Komut 2 ; . . . }
Belirli bir kelimeyi bir text dosyası içinde araştırmak istediğimizde grep komutu devreye girer.
$ grep “sort” *.doc
$ grep “sort it” *
Yukarıdaki örneklerden ilkinde “sort” kelimesi .doc dosyalarında, “sort it” kelimesi tüm dosyalarda aranacaktır.
$ grep –c “48” data.f
Bu komutla data.f dosyasında 48 rakamı içeren satır sayısı görüntülenir.
Kabuk programlamada her tip tırnak atomunun (atom: bir programlama dilinin ayrılmaz en küçük parçası; örnek olarak && iki karakterden oluşsa da, AND mantıksal ifadesini gösteren tek bir atomdur ve ayrı yazılamaz) farklı anlamlara geleceğini bilmeliyiz:
$MTVAR = /dev/hda*
$echo “$MYVAR”
/dev/hda*
$echo $MYVAR
/dev/hda /dev/hda1 /dev/hda2 /dev/hda5 /dev/hda7 İlk örnekte gösterilen çift tırnaklı atomda değişken atanan değerin içeriğine sahip değildi ve gösterildiği şekli ile korundu. İkincisinde değişkene atanan değerin işlevi gerçekleştirilmiş oldu. Değer bir yerel değişken atama şekli ise :
${variable:-value} (burada variable’a bir değer atanmış ise o değer kullanılır.)
$ COLOUR = blue
$echo “The sky is ${COLOUR:-grey} today”
The sky is bule today
$ COLOUR = blue
$ unset COLOUR
$ echo “The sky is ${COLOUR:-grey} today”
The sky is grey today
Sistem komutlarını tutmak için değişkenler kullanılabilir.
$ SOURCE = “/etc/passwd”
$ DEST = “/tmp/passwd.bak”
$ cp ${SOURCE} ${DEST}
Konuma Bağlı Değişken Parametreleri
:Kabuk betiğine herhangi bir bilgiyi yollamak istediğimizde bunu konumsal parametre kullanarak yapabiliriz. Parametreler 1 den başlayıp 9’a kadar devam eder. Ulaşmak istediğimiz herhangi bir parametre başında $ işareti yer alır. İlk parametre 0 ile başlayıp parametre betik adını alır. Örneğin <<Did you see the full moon>> yazısını bir betiğe geçirmek istediğimizde:
$0 $1 $2 $3 $4 $5 $6 $7 $8 $9
Betik adı Did you see the full Moon
#!/bin/sh
#parametre
echo “Bu betik adidir :$0”
echo “Bu ilk parametredir :$1”
echo “Bu ikinci parametredir :$2”
echo “Bu üçüncü parametredir :$3”
…………
…………
echo “Bu dokuzuncu parametredir :$9”
Program şu şekilde çalışacaktır:
$Did you see the Full Moon
Bu betik adidir :./ parametre Bu ilk parametredir :Did
Bu ikinci parameterdir :you Bu üçüncü parametredir :see Bu dördüncü parametredir :the Bu beşinci parametredir :Full Bu altıncı parametredir :Moon Parametrik sistem komutlara da geçebilir :
#!/bin/sh
# Dosya Bul
find / - name $1 –print
$Dosya Bul passwd /etc/passwd
/etc/uucp/passwd /usr/bin/passwd
Özel kabuk değişkenleri :
$# Betiğe geçirilen argüman sayısı
$* Betiğe geçirilen tüm argümanları tek bir string (process ID) olarak gösterir.
$$ Çalışmakta olan betiğin o anki PID sini verir.
$! Geri plana atılan son proses için PID sini verir.
$ @ Gerçekte $# ile aynıdır, eğer tırnak işareti ile kullanılırsa her argümanda tırnak işareti içerisinde geri döner.
$? Son komutun çıkış durumunu gösterir. Eğer o ise hata yok diğerlerinde hata vardır.
Kabukta kullanılan tırnak işaretleri :
“ “ çift tırnak
‘ ‘ tek tırnak
´ ´ grave veya geri tırnak
\ back slash
tek tırnak çift tırnağa çok benzer olup tek farkı kabuğa tek tırnak içerindeki herhangi bir değer hesaplanmasını ihmal etmesini söyler.
$ GIRL = ´girl´
$ echo = “The ‘$GIRL’ did well”
The ´girl´ did well
Geri tırnak değişkeni, sistem komutlarından değişkenlere bir değer atanması söz konusu olduğunda kullanılır :
$ echo ‘hello’
sh: hello . commanda not found
$ echo ‘date’
Sun May16:40:19 GMT 1999
$echo “The date today is ‘date’”
The date today is Sun May 16 16:40:19 GMT 1999
$echo “There are ‘who \ we -1’ users on the system”
There are 13 users on the system
\ (back slash) : Sonraki karakterin eğer kabuk için özel bir anlamı varsa bunun yanlış yorumlanmasını engeller.
Örneğin, o anki PID yi görüntüleyen $$ komutu için :
$ echo $$
284
$ echo \$$
$$
Oktal karakterleri görüntülemede de kullanılır.
$ echo “This is copyright 251 sign”
This is copyright \251 sign
$echo –e “This is copyright \251 sign”
This is copyright sign
$ expr 12 \*12 144
$echo –e “ Bu video \$19,99 dır”
Bu video $19,99 dır.
Kabuk Betiğinin Çalıştırılması :
#!/bin/sh
# name: cleanup
# This is general cleanup script echo “Starting cleanup ………… wait”
rm /usr/Lcoal/apps/log/*.log
tail -40 /var/adm/message > /tmp/message rm /var/adm/messages
mv /tmp/messages /var/adm/messages echo “finished cleanup”
$ chmod u+x cleanup
$ cleanup (Eğer bir hata oluşuyorsa)
$ ./cleanup (Eğer hala çalışmıyorsa)
Bu durumda /bin klasörünü ev dizinimize ilave etmemiz gerekecek :
$ pwd
$ /home/mscelebi/bin
.profile dosyasını düzenleyelim :
PATH = $ PATH : $HOME / bin
Eğer bin klasörü yoksa ilave edelim : $ cd $HOME
$ mkdir bin
Yeniden .profile dosyasını aktive edelim : $ . ./profile
Şartlı Test :
Bir dosyanın durumunu test etmek : test şart
veya
[ şart ]
Köşeli parantezin sağında ve solunda birer boşluk bırakıldığına dikkat edin!!!
Test komutunun aritmetik işlemlerde kullanımı ile ilgili bilgi ise ileride verilecektir.
7.4 Aritmetik İşlemler
‘bash’ kabuğunda matematiksel işlemlere büyük sınırlamalar getirilmiştir. Tamsayı değişkeni dışında matematiksel değişken kullanmak için bu işlemler için geliştirilmiş ve kolaylıklar sağlayan awk veya bc yi kullanabilirsiniz.
Aritmetik işlemler için eval komutunu veya bash kabuğu altında yerleşik (built in) komut olan let komutunu kullanabilirsiniz. Aşağıda let komutunun kullanımı görülüyor.
let "degisken=aritmetik islem"
Bu örnekte iki sayı çarpılıp çıkan sonuç başka bir değişkene yazılıyor.
$ let "carpim=2*7"
$ echo $carpim
Aritmetik değişken tanımlamanın diğer bir yolu da typeset komutu kullanmaktır.
$ typeset -i sonuc (sonuc degiskeni bir dogal sayi icerecek)
$ a=100 ; b=56 (iki komutu ayirmak icin ; kullanilabilir)
$ sonuc=a*b
$ echo $sonuc 5600
7.5 if-else Kalıbı ve Kontrol İşlemleri
Hemen her programlama dilinde olan ‘if’ kalıbı bir Linux komutunun çalışmasını kontrol eder. ‘if’ komutu yerleşik bir komuttur ve her if, bir ‘fi’ komutuyla bitmelidir. if komutunun ardından gelen Linux komutu çalıştırılır ve komutun çıkış durumu (exit status) gözönüne alınarak ardından gelen ‘then’ deyimiyle birlikte devamı işletilir.
Genellikle komutun iki türlü çıkış durumu olacağından else komutunun ardından gelen komut zinciri, diğer çıkış durumunda çalıştırılır. Aşağıda if-else-then komutunun örnek sözdizimi görülüyor.
if linux komutu then komut1
komut2 ...
else komut1 komut2 ...
fi
grep komutu kullarak bir örnek yapalım:
#!/bin/sh
# grepif
if grep ‘Dave\>’ data.file > /dev/null 2>&1 then
echo “Great, Dave is in the file”
else
echo “No Dave is not in the file”
fi
$ grepif
No Dave is not in the file
Eğer match başarılı olsaydı, grep 0 değeri verecekti.
if komutu genellikle kendine ‘test’ komutu ile birlikte kullanım bulur. Bu komut yardımıyla mantıksal işlemler yapılabilir, sayılar ve hatta diziler karşılaştırılabilir. Anahtar sözcük olan test'ten sonra seçenekler ve/veya karşılaştırılacak olan değerler yazılır. Her seçenek bir mantıksal işleme karşılık gelir. Örneğin -lt seçeneği ilk girilen aritmetik değişkenin ikinci değerden küçük olup olmadığını denetler. Benzer şekilde = seçeneği de iki karakter kümesinin eşitliğini kontrol eder. Aşağıda test komutunun örnek kullanımı yeralıyor.
$ test 5 -eq 3
$ a="linux"
$ test $a="linux"
komutun işletilmesinin ardından kabuğa bir değer gönderilir. Bu değer komut başarılı olarak işletilmişse 0, değilse 1'dir. Son çalıştırılan tüm Linux komutlarının çıkış değeri $?
değişkeninde tutulur. test komutunun çıkış değeri de bu yolla öğrenilebilir.
$ sayi=4
$ test $sayi -eq 4
$ echo $?
0
$ test $sayi -lt 2
$ echo $?
1
Basit Bir Güvenlik Giriş Betiği :
Aşağıda kullanıcı sisteme girdiğinde uygulama programınızı devreye almadan önce ilave bir güvenlik oluşturma işlemi verilmiştir. Önce kullanıcı ismi ve parola sorulmaktadır, eğer kullanıcı ismi ve parola betikte verilen parola ile benzeşirse kullanıcı girer, benzeşmez ise kullanıcı giremez.
$ pg ifpass
#!/bin/sh
# ifpass
# set the variable to false INVALID_USER = yes
INVALID_PASSWD = yes
# save the current stty setting SAVEDSTTY = ‘stty –g’
echo “you are logging a sensetive area”
echo -n “Enter your ID name: “ read NAME
# hide the characters type in stty –echo
echo “Enter your password : “ read PASSWORD
#back on again stty $SAVEDSTTY
if [ “$NAME” = “dave”] || [“$NAME” = “pauline”]; then
#if a valid then set variable INVALID_USER = no
fi
if [ “$PASSWORD” = “mayday”]; then
# if valid password then set variable INVALID_PASSWD = no
fi
if [“$INVALID_USER” = “yes” –o “$INVALID_PASSWD” = “yes” ];
then
echo “’basename $0 :‘ Sorry wrong password or userid”
exit 1 fi
# if we get here then their ID and password are OK.
echo “correct user id and password are given”
Yukarıdaki betik yanlış bir password verilerek çalıştırıldığında :
$ ifpass
Your are logging into a sensetive area Enter your ID name : dave
Enter your password :
ifpass : Sorry wrong password or userid Doğru bir kullanıcı ismi ve password verilerek çalıştırıldığında :
$ ifpass
You are logging into a sensetive area Enter your name : dave
Enter your password :
Correct user id and password given
test komutu yerine parantezler de kullanılabilir. Yukarıdaki iki örnek, parantez kullanılarak şu şekilde yazılabilir:
$ [ $sayi -eq 4 ]
$ [ $sayi -lt 12 ]
Dikkat edilmesi gereken bir nokta, köşeli parantez kullanırken araya boşlukların eklenmesidir.
Parantezler başlı başına bir komut olarak görüldüklerinden sağında ve solunda en az bir boşluk bırakılmalıdır. test komutunda sıkça kullanılan diğer seçenekler şunlardır :
Aritmetik karşılaştırmalar : -gt büyük
-lt küçük -ge büyükeşit -le küçükeşit -eq eşit -ne eşit değil
Dizisel karşılaştırmalar : -z boşdizi
-n tanımlı dizi
= eşit diziler
!= farklı diziler Dosya karşılaştırması : -d bu bir klasördür
-l bu bir sembolik link’tir -u bu dosyanın suid i vardır.
-f dosya var -s dosya boş değil -r dosya okunabilir -w dosyaya yazılabilir -x çalıştırılabilir dosya -h sembolik bağlantı -c karakter aygıt -b blok aygıt Örnekler:
$ test –w scares.txt $ [ -w scares.txt]
$ echo $? $ echo $?
0 0
Her iki değerde de sıfırdır ve bu dosyanın yazılabilir olduğunu gösterir.
$ [ -x score.txt ] $ echo $?
1 ( dosya çalıştırılamaz)
Mantıksal karşılaştırmalar : -a VE
-o VEYA
! DEĞİL Bir örnek :
$ [ -w results.txt –a –x results.txt]
$ echo $?
0
(results.txt dosyası hem çalıştırılabilir hemde yazılabilir)
if komutunun test ile birlikte kullanılabildiğini daha önce belirtmiştik. Aşağıda bununla ilgili küçük bir örnek yer alıyor:
#!/bin/bash
echo "0 ile 20 arasinda bir sayi secin"
read sec
if [ $sec -lt 10 ] then
echo "Secilen sayi tek basamakli"
else
echo "Secilen sayi cift basamakli"
fi
7.6 case Kalıbı
Birkaç alternatif arasından seçim yapmak için kullanılan bir komut olan case, bir eşleştirme gördüğü anda belirli bir komut kümesini işleme sokar. Case yapısı ‘case’ komutu ile başlar, eşleştirilecek olan anahtar sözcük yazılır ve seçenekler alt alta, her seçeneğe ait olan komutlarla birlikte belirtilir. Tüm yapı ‘esac’ komutu ile son bulur :
case anahtar-sözcük in seçenek1) komutlar ;;
seçenek2) komutlar ;;
*) komutlar ;;
esac
Seçenekler arasında özel karakterler (*, [] , ? gibi) kullanılabilir. Hiçbir eşleme yapılmadığı zaman *) seçeneği değerlendirilecek ve buna bağlı olan komutlar işletilecektir. * kullanımı isteğe bağlıdır. Aşağıda case komutuna ilişkin kısa bir örnek veriliyor.
#!/bin/bash clear
echo "1. ekrani temizle"
echo "2. sistemdekileri goruntule"
echo "3. dizindeki dosyalari goster"
echo -n "Secenegi giriniz : "
read secenek case $secenek in 1)
clear ;;
2) w ;;
3)
ls -al ;;
*)
echo Hatali secenek esac
Bu özel karakterlerin anlamları şunlardır:
* herhangi bir karakter
? herhangi tek karakter
[..] herhangi karakter (bir sınıf veya aralıkta)
| sembolü ( or komutu yerine) kullanılarak belirli bir pattern oluşturabiliriz.
Örneğin;
vt100 | vt102 vt100 veya vt102 anlamına gelecektir. Şimdiki örnekte belirli bir terminal tipi getirilerek kontrol yapılmasını inceleyeceğiz:
Bu örnekde kullanıcının terminal tipini girmesi sorulacaktır. Eğer kullanıcı vt100 veya vt102 girerse case patern ninde bir benzeşim olacaktır. case yapısı dışında TERM değişkeni export edilecektir.
$ pg caseterm
#!/bin/sh
#caseterm
echo “ choices are .. vt100, vt102, vt220”
echo –n “enter your terminal type:”
read TERMINAL
case $TERMINAL in
vt100|vt102) TERM = vt100 ;;
vt100|vt220) TERM = vt220 ;;
*)echo “ ‘basename $0’ : Unknown response” >&2 echo “setting it to vt100 anyway, so there”
TERM = vt100 ;;
esac
export TERM
echo “Your terminal is set to $TERM”
Betik çalıştığında ve geçersiz bir terminal tipi verdiğimizde:
$ caseterm
choice are….vt100, vt102, vt220 enter your terminal type : vt900 caseterm : Unknown response
setting it to vt100 anyway, so there Your terminal is set to vt100
Doğru bir terminal tipi verdiğimizde :
$ caseterm
choices are…. Vt100, vt102, vt220 enter your terminal type : vt220 Your terminal is set to vt220
$pg caseans
#!/bin/sh
#caseans
echo -n "Do you wish to proceed [y…n]: "
read ANS
case $ANS in
y|Y|yes|Yes) echo "yes is selected"
;;
n|N) echo “no is selected”
exit 0 #no error so only use exit 0 to terminate ;;
*) echo " 'basename $0' : Unknown response" >&2 exit 1
;;
esac
# if we are here then a y|Y|yes|Yes was selected only.
Geçerli olmayan bir girişle çalıştırdığımızda :
$ caseans
Do you wish to proceed [y..n] :df caseans : Unkown response
Ve geçerli bir giriş ile çalıştırdığımızda:
$ caseans
Do you wish to proceed [y..n] :y yes is selected
7.7 Döngüler
Diğer hemen tüm programlama dillerinin en büyük gücü olan döngü işlemlerine kabuk altında da izin verilmektedir. Burada programcı tarafından en çok kullanılan iki döngü tipi anlatılacaktır: while ve for. while komutu her döngüde bir denetleme mekanizmasını harekete geçirirken, for döngüsü daha değişik bir mantıkla çalışır.
7.7.1 while-do Döngüsü
Döngü bloğu while anahtar kelimesiyle başlar, ardından gelen koşul sağlandığı sürece döngü işletilir. Önce koşulun sağlanıp sağlanmadığına bakılır. Döngüden çıkabilmek için mutlaka döngü içindeki koşul ifadesinin değerini yanlış yapacak bir durum oluşmalıdır, aksi halde sonsuz döngü oluşur.
while ko ul ifadesi do
komutlar done
if komutuyla birlikte kullanılan test komutu, while döngüsünde koşul ifadesi olarak da yer alabilir. Aşağıda 1'den 100'e kadar sayan ve ekrana basan bir döngü görülüyor:
#!/bin/bash deger=0
while [ $deger -lt 100 ] do
deger=$((deger+1)) echo $deger
done
Yukarıda kullanılan (( ... )) karakterleri arasına matematiksel bir işlem getirilebilir. Bu özellik bash kabuğuna özgüdür.
7.7.2 for-do döngüsü
Bir liste dahilindeki tüm değerlere sırayla erişimi sağlar. for komutundan sonra yer alan liste sırayla kullanılır ve herbirisi için döngü çalıştırılır. Listenin sonuna gelindiğinde ise döngüden çıkılır.
for degisken1 in deger1 deger2 ... degerX do
komutlar done
Aşağıdaki örnek bu döngüyü kullanarak ekrana bir dizi kelime yazıyor. Döngü boyunca akasya, elma ve visne kelimeleri "agac" değişkenine kopyalanıyor ve her döngüde bu değişkenin içerdiği bilgiler ekrana yazılıyor.
for agac in akasya elma visne do
echo $agac done
for-do döngüsü, dosya isimleri üzerinde yapılan işlemlerde de büyük kolaylıklar sağlar.
Bunun için özel karakterlerden yararlanmak da olasıdır. Örnek olarak * karakteri o anki çalışma dizini içindeki tüm dosyaları seçer.
for a in *.pl ; do file $a done
Birkaç başka örnek:
(1)
#!/bin/sh
# for_i for loop in 1 2 3 4 5
do
echo $loop done
Çalıştırdığımızda:
$ for_i 1
2 3 4 5 (2)
#!/bin/sh
#forls
for loop in ‘ls’
do
echo $loop done
$forls
(3)
Dosyaların kopyalanması
#!/bin/sh
# forcp
BAK = “.bak”
for loop in ‘ls’
do
echo “Copying $loop to $loop$BAK”
cp $loop $loop$BAK done
7.7.3 until-loop döngüsü Until kou l
...komutlar...
………
done
Aşağıdaki betik root un sisteme girmesini bekler, root sisteme girer girmez kullanıcı Serdar’a mail yollanır.
#!/bin/sh
#until_who
IS_ROOT = ‘who | grep root’
Until [“$IS_ROOT”]
do
sleep 5 done
echo “Dikkat et root sisteme girdi” | mail Serdar