|
|
| Bu makalenin farklı dillerde bulunduğu adresler: English Castellano Deutsch Francais Nederlands Portugues Turkce |
tarafından Katja and Guido Socher Yazar hakkında: Katja LinuxFocus'un Alman editörüdür. Tux, film, fotografçılığı ve denizi sever. Ana sayfasına buradan ulaşabiliriz. Guido uzun zamandan beri bir Linux hayranı ve Linux'u dürüst ve açık insanlar tarafından tasarlandığı için seviyor. İşte bu ona açık kodlu dememizin bir nedeni... Guido'nun sanaldoku sayfası: linuxfocus.org/~guido İçerik: |
Özet:
Bu yazıda küçük bir kabuk betiğinin nasıl yazılacağı pek çok örnekle veriliyor.
#!/bin/sh
The #! karakterleri sisteme, bu karakterleri takip eden argumanın bu dosyayı çalıştırmakta kullanacağını söyler.
Burada kullandığımız kabuk /bin/sh 'dır.degisken=degerDeğeri görmek için değişkenin önüne dolar işareti koymak yeterlidir:
#!/bin/sh # Bir değer ata: a="Merhaba Dünya" # Şimdi "a" nın değerini yaz: echo "a nın değeri:" echo $aBu satırları metin editörünüzde yazın ve "first" ismiyle kayıt edin. Sonra chmod +x komutuyla betiği çalıştırılabilir yapın ve ./first komutuyla çalıştırın.
a nın değeri: Merhaba DünyaBazen bu durum yazının diğer kısımlarıyla değişken isimlerinin karışmasına yol açabilir.
num=2 echo "this is the $numnd"Bu "this is the 2nd" yazmayacaktır.Çıktı : "this is the " olacaktır. Çünkü betik numnd adı verilen değişkeni arayacak ve bir değere sahip olmadığını bulacaktır. Burada parantezleri kullanırsak :
num=2
echo "this is the ${num}nd"
Bu istediğimizi yazacaktır: this is the 2nd | Komut kullanımı (syntax) | Amaç |
|---|---|
| echo "metin kısmı" | Metin kısmını ekrana yazar. |
| ls | Dosyaları listeler. |
| wc -l dosya wc -w dosya wc -c dosya |
Dosyadaki stırları sayar veya sözcükleri veya karatkterleri sayar. |
| cp kaynakdosya hedefdosya | Kaynakdosya'yı hedefdosya olarak kopyalar. |
| mv eskiad yeniad | Dosya adını değiştirir veya dosyayı taşır. |
| rm dosya | Dosya siler. |
| grep 'katar' dosya | Dosya içerisinde katar arar. Örnek: grep 'aranacak katar' dosya.txt |
| cut -b sütün dosya | Sabit uzunluklu metin sütünlarından veri elde etme. Örnek: 5 ile 9 arasındaki karakterleri elde eder. cut -b5-9 dosya.txt Bu komutu bam başka bir komut olan "cat" ile karıştırmayın. |
| cat dosya.txt | dosya.txt'yi standart çıktı aygıtına yazar (sizin ekranınız). |
| file dosya | Dosyanın tipi hakkında bilgi vermektedir. |
| read değişken | Kullanıcıdan aldığı değeri değişken'e yazar. |
| sort dosya.txt | dosya.txt'daki satırları sıralar(dizer). |
| uniq | Tekrarlanan satırları siler. Sadece arka arkaya gelen ve tekrarlanan
satırları sildiği için sort ile birlikte kullanılabilir. Örnek: sort dosya.txt | uniq |
| expr | Kabuk içerisinde matematiksel işlemler yapar. Örnek: 2 ile 3 toplamak için expr 2 "+" 3 |
| find | Dosya araması yapar. Örnek: dosya ismine göre arama: find . -name dosyaismi -print Aslında bu komutun birçok kullanımı vardır ve hepsini bu yazıda anlatmak ne yazık ki olası değildir. |
| tee | Standart çıktı aygıtına (sizin ekranınız) veri yazmak. Genellikle şu şekilde kullanılır:|
| basename dosya | Yoltanımı(dizin) kısmını atarak sadece dosyanın adını üretir.
Örnek: basename /bin/tux Sadece tux elde edilir. |
| dirname dosya |
Dosya adınını atarak sadece yoltanımını (dizin) üretir.
Örnek: dirname /bin/tux Sadece /bin kısmı elde edilir. |
| head dosya | Dosya başından itibaren birkaç satır yazar. |
| tail dosya | Dosya sonundan itibaren birkaç satır yazar. |
| sed | sed basit olarak bul ve değiştir programıdır.
Ekrandan (veya borudan) okuduğu metinleri standart
çıktı aygıtına (genelde ekran) yazar.
Aranan metin düzenli ifadedir (kaynaklar
kısmına bakınız). linuxfocus katarını LinuxFocus ile değiştirmek için : cat metin.dosyası | sed 's/linuxfocus/LinuxFocus/' > yenimetin.dosyası kullanabilirsiniz. Bu her satırdaki linuxfocus'ları LinuxFocus ile değiştirir. Eğer, aynı satırda birden fazla linuxfocus varsa, sadece ilkini değiştirir. Bir satırdan birden fazla aynı ifadeden varsa ve siz bunu değiştirmek istiyorsanız: cat metin.dosyası | sed 's/linuxfocus/LinuxFocus/g' > yenimetin.dosyası |
| awk |
Genellikle awk bir satırdaki alanları elde etmek için kullanılmaktadır.
Benimsenmiş değer olarak, alan ayracı, boşluk karakteridir. Başka bir
alan ayracı belirtmek için -F seçeneği kullanılabilir.
cat dosya.txt | awk -F, '{print $1 "," $3 }'
Burada ayraç olarak virgül (,) karakteri kullanıldı ve ilk ve üçüncü ($1 $3)
alanlar (sütünlar) elde edildi. Eğer, dosya.txt'nin satırları şu şekilde ise:
Adam Bor, 34, India Kerry Miller, 22, USAo zaman sonuç: Adam Bor, India Kerry Miller, USAolur. Awk ile bundan çok daha fazlasını yapmak olasıdır. Bu sadece en çok kullanılan şeklidir. |
grep "merhaba" dosya.txt | wc -l
dosya.txt dosyasındaki merhaba kelimesini içeren satırları bulmakta ve onları saymaktadır.find . -mtime -1 -type f -printKomutu, 24 saat içerisinde değiştirilmiş tüm dosyaları bulmaktadır. (-mtime -2 ise, 48 saat olura). Eğer, bütün bu dosyaları bir tar dosyası (dosya.tar) haline getirmek istiyorsanız :
tar xvf dosya.tar dosya1 dosya2 ...Tüm dosyaları tek tek yazmaktansa, iki (find ve tar) komutu ters tırnak kullanarak birleştirebiliriz. Böylece, tar komutu, find komutunun bulduğu tüm dosyaları paketleyecektir:
#!/bin/sh
# Tırnaklar ters tırnaktır (`), normal tırnak değil ('):
tar -zcvf ensondegisen.tar.gz `find . -mtime -1 -type f -print`
if ....; then .... elif ....; then .... else .... fiGenelde, if ifadesi, içerisinde test adı verilen bir komut kullanılmaktadır. Bu komut katar karşılaştırılmasında, dosyanın var olup olmadığının denetlenmesinde, dosyanın okuma hakkı olup olmadığını denetlenmesinde ... kullanılmaktadır.
[ -f "dosya" ] : "dosya" nın dosya olup olmadığını denetler.
[ -x "/bin/ls" ] : /bin/ls çalıştırılabilir bir dosya olup olmadığını denetler.
[ -n "$değisken" ] : $degisken'in herhangi bir değer taşıyıp taşımadığını
denetlemektedir.
[ "$a" = "$b" ] : "$a" nın "$b" ye eşit olup olmadığını denetlemektedir.
"man test" komutunu çalıştırarak, tüm karşılaştırma ve dosya
denetleme seçeneklerini elde edeceksiniz.#!/bin/sh if [ "$SHELL" = "/bin/bash" ]; then echo "Giriş kabuğunuz bash (bourne again shell) dır." else echo "Giriş kabuğunuz bash değil $SHELL dir" fi$SHELL değişkeni kullanılan kabuğun ismini içermektedir ve biz onu "/bin/bash" ile karşılaştırıyoruz.
[ -f "/etc/shadow" ] && echo "Bu bilgisayar gölge şifrelemesi
(shadow passwords) kullanıyor."
&& ifadesi if-ifadesine kısayol gibi kullanılabilir.
İfadenin sağ tarafı ancak sol tarafı doğru olduğunda çalıştırılmaktadır.
Bunu VE (AND) gibi okuyabilirsiniz. Buna göre : "/etc/shadow dosyası
var VE echo çalıştırılmaktadır". VEYA (||) işlemcisi de vardır. Örnek:
#!/bin/sh
eiletidizini=/var/spool/mail/james
[ -r "$eiletidizini" ] || { echo "$eiletidizini dizinini okuyamıyorum" ; exit 1; }
echo "$eiletidizini de eiletiniz var.:"
grep "^From " $eiletidizini
Bu kabuk betiği e-ileti dizinini okuyup okuyamadığna bakmaktadır.
Eğer, okuyabiliyorsa, dosyadan "From" içeren satırları ekrana yazmaktadır.
Eğer $eiletidizini dosyasını okuyamıyorsa, VEYA işlemcisi devreye girmektedir.
Normal İngilizce'de program parçasını şu şekilde okuyoruz: "E-ileti dizini okunabilir
veya çık.". Buradaki sorun, VEYA'dan sonra sadece bir komuta yer olmasıdır, ancak bizim birden
fazla komuta gereksinimiz vardır:
case ... in ...) burada birşeyler yap;; esacBir örnek ele alalım. Bir dosyanın tipini fıle komutunu kullanarak öğrenebiliriz:
file lf.gz sonuç: lf.gz: gzip compressed data, deflated, original filename, last modified: Mon Aug 27 23:09:18 2001, os: UnixŞimdi biz bu komutu smartzip adında, otomatik olarak sıkıştırılmış (uncompress, bzip2, gzip ve zip) dosyaları açan bir kabuk programı yazımında kullanacağız:
#!/bin/sh
ftype=`file "$1"`
case "$ftype" in
"$1: Zip archive"*)
unzip "$1" ;;
"$1: gzip compressed"*)
gunzip "$1" ;;
"$1: bzip2 compressed"*)
bunzip2 "$1" ;;
*) error "File $1 dosyası smartzip ile açılamıyor.";;
esac
select var in ... ; do break done .... şimdi $var kullanılabilir ....İşte örnek:
#!/bin/sh
echo "En favori işletim sisteminiz hangisidir?"
select var in "Linux" "Gnu Hurd" "Free BSD" "Diğer"; do
break
done
echo "Seçiminiz $var dur."
Kabuk programı şunları gerçekleştirmektedir:
En favori işletim sisteminiz hangisidir? 1) Linux 2) Gnu Hurd 3) Free BSD 4) Diğer #? 1 Seçiminiz Linux dur."Kabukta kullanabileceğiniz döngü ifadeleri şunlardır:
while ...; do .... donewhile-döngüsü denetlenen ifade doğru olduğu sürece çalışılacaktır. Döngünün herhangi bir noktasından çıkmak için "break" kullanılabilir. Döngünün herhangi bir yerinde "continue" kullanılırsa, döngünün geriye kalanı çalıştırılmamakta ve onun yerine döngünün başına dönülmektedir.
for değişken in ....; do .... doneAşağıdaki örnekte A dan C'ye kadar olan karakterler ekrana yazmaktadır:
#!/bin/sh for degisken in A B C ; do echo "değişkenin değeri $degisken" doneAşağıda daha kullanışlı bir örnek yer almaktdadır. Örnek, rpmgoster adını taşımakta ve parametre olarak verilen rpm paketleri hakkında bilgi elde etmekte ve ekranda göstermektedir:
#!/bin/sh
# RPM paketlerinin içeriğini listeler
# KULLANIM: rpmgoster rpmdosya1 rpmdosya2 ...
# ÖRNEK: rpmgoster /cdrom/RedHat/RPMS/*.rpm
for rpmpaketi in $*; do
if [ -r "$rpmpaketi" ];then
echo "=============== $rpmpaketi =============="
rpm -qi -p $rpmpaketi
else
echo "HATA: $rpmpaketi dosyası okunamadı."
fi
done
Yukarıdaki örnekte komut satırından verilen ve tüm parametreleri içeren
$* değişkenini görüyorsunuz. Programı, #!/bin/sh echo *.jpgBu ekrana "eileti.jpg tux.jpg" yazacaktır.
#!/bin/sh echo "*.jpg" echo '*.jpg'Bu ise, ekrana "*.jpg" ifadesini iki kez yazmaktadır.
#!/bin/sh echo $SHELL echo "$SHELL" echo '$SHELL'Sonuç aşağıdaki gibi olacaktır:
/bin/bash /bin/bash $SHELLSon olarak, özel anlam taşıyan herhangi bir karakteri yazmak için önüne ters bölü çizgisi kullanabiliriz:
echo \*.jpg echo \$SHELLdolayısıyla:
*.jpg $SHELLelde edilir.
#!/bin/sh
# Eğer, 3'ten daha az paramtre verilmişse, yardım mesajı görüntülenecektir:
if [ $# -lt 3 ] ; then
cat <<YARDIM
ren -- birden fazla dosyanın adını sıradan ifadeler kullanarak değiştirmektedir.
KULLANIMI: ren 'sıradanifade' 'yerinekonulacakifade' dosyalar...
ÖRNEK: tüm *.HTM dosyalarını *.html olarak değiştirmek için:
ren 'HTM$' 'html' *.HTM
YARDIM
exit 0
fi
ESKI="$1"
YENI="$2"
# shift komutu, komut satırından verilen parametre listesinden
# bir adet parametreyi silmektedir
shift
shift
# Şimdi $* tüm dosyaları içermektedir:
for dosya in $*; do
if [ -f "$dosya" ] ; then
yenidosya=`echo "$dosya" | sed "s/${ESKI}/${YENI}/g"`
if [ -f "$yenidosya" ]; then
echo "HATA: $yenidosya zaten var"
else
echo "$dosya sı $yenidosya olarak değiştirilmektedir ..."
mv "$dosya" "$yenidosya"
fi
fi
done
Bu şu ana kadar incelediğimiz en karmaşık betiktir. Bunun üzerinde biraz
konuşalım. İlk if-ifadesi, komut satırından verilen parametre
sayısının en azından 3 adet olup olmadığını denetlemektedir.
(Özel bir değişken olan $# de parametre sayısını tutmaktadır.)
Eğer, parametre sayısı yeterli değil ise, yardım mesajı cat komutuna,
o da ekrana göndermektedir. Yardım mesajı görüntülendikten sonra programdan
çıkılmaktadır. Eğer, 3 veya daha fazla parametre verilmiş ise, ilki ESKI,
ikincisi de YENI değişkenlerine atanmaktadır. Daha sonra, shift komutu iki defa kullanılarak
3. paramtreyi ilk parametre olarak elde etmek için kaydırılmaktadır.
$* daki her parametre tek tek $dosya değişkenine atanmaktadır.
İlk önce dosyanın var olup olmadığı denetlenmektedir ve ondan sonra
yeni dosya adı eskisi üzerinde sed komutuyla yapılan değiştirme
ile elde edilmektedir. Ters tırnaklar, yeni dosya isminin yenidosya değişkenine atamak
için kullanılmıştır. Artık gereksinim duyduğumuz herşeye sahibiz: eski dosya
adına ve yenisine. Bu ikisi mv komutuna parametre olarak verilerek,
eski dosya ismi yenisi ile değiştirilmektedir.
fonksiyonismi()
{
# Fonksiyon gövdesinde (içerisnde) $1, fonksiyona verilen ilk parametre
# $2 ikinci vs.
fonksiyonun gövdesi
}
Fonksiyonu kullanmadan önce, programın başında fonksiyonu "tanımlamak"
gerekmektedir.
#!/bin/sh
# vim: set sw=4 ts=4 et:
yardim()
{
cat <<YARDIM
xtitlebar -- xterm, gnome-terminal veya kde konsole un adı değiştirir.
KULLANIMI: xtitlebar [-h] "başlık"
SEÇENEKLER: -h yardim metin
ÖRNEK: xtitlebar "cvs"
YARDIM
exit 0
}
# Hata durumunda veya -h parametresi verildiğinde yardim
# fonksiyonunu çağırmaktayız:
[ -z "$1" ] && yardim
[ "$1" = "-h" ] && yardim
# konsole'un başlığını değiştirmek için kaçış kodu gönder:
echo -e "\033]0;$1\007"
#
Yazdığınız programlarda geniş yardım bilgilerine yer vermeniz
iyi bir alışkanlıktır. Bu size ve başkalarına programı kullanırken
oldukça faydalı olmaktadır.
#!/bin/sh
yardim()
{
cat <<YARDIM
Bu genel bir parametre işlemcisidir.
ÖRNEK KULLANIM: cmdparser -l merhaba -f -- -dosya1 dosya2
YARDIM
exit 0
}
while [ -n "$1" ]; do
case $1 in
-h) yardim;shift 1;; # yardım fonksiyonu çağrıldı
-f) opt_f=1;shift 1;; # opt_f değişkenine değer atandı
-l) opt_l=$2;shift 2;; # -l parametresi değer almaktadır,
-> shift ile 2 kaydırıldıktan sonar
--) shift;break;; # seçenekler bölümünün sonu
-*) echo "hata: $1 seçeneği tanımlı değildir. yardım için -h";exit 1;;
*) break;;
esac
done
echo "opt_f nin değeri $opt_f"
echo "opt_l nin değeri $opt_l"
echo "ilk parametre $1"
echo "ikinci parametre $2"
Bunu bir deneyin! Programı aşağıdaki gibi çalıştırabilirsiniz:
cmdparser -l merhaba -f -- -dosya1 dosya2sonuç
opt_f nin değeri 1 opt_l nin değeri merhaba ilk parametre -dosya1 ikinci parametre dosya2Bu nasıl çalışmaktadır? Döngü içinde tüm parametreler tek tek case ifadesindekilere uyup uymadığı karşılaştırılmaktadır. Uyuan bir parametre bulunduğunda, değeri ilgili değişkene atanmakta ve bir kaydırılmaktadır. Unix'te, seçimler (- eksi işareti ile başlayanlar) önce gelmektedir. İki eksi (--) çizgisiyle seçimlerin bittiğini belirtebilirsiniz. Buna, eksi ile başlayan bir katarı grep ile ararken gereksiminiz olacaktır:
f.txt dosyasında -xx- arama: grep -- -xx- f.txtBizim parametre işlemcimiz, yukarıda da görüldüğü gibi, -- ile başlayan parametreleri de işleyebilmektedir.
cp framework.sh benimprogramve bundan sonra "benimprogram" adlı programda gerekli değişiklikler yapılabilir.
#!/bin/sh
# vim: set sw=4 ts=4 et:
yardim()
{
cat <<YARDIM
b2h -- ikili sayı sisteminde verilen bir sayıyı, onlu sayı sisteme çevirir
KULANIM: b2h [-h] ikilisayi
SEÇENEKLER: -h yardım metin
ÖRNEK: b2h 111010
için sonuç 58 olur
YARDIM
exit 0
}
hata()
{
# hata mesajını görüntüle ve çık
echo "$1"
exit 1
}
sonkarakter()
{
# $rval değişkeni içerisine, verilen katarın son karakterini yerleştirir
if [ -z "$1" ]; then
# boş katar
rval=""
return
fi
# wc, çıktının sonuna biraz boşluk koymaktadır,
# sed'e gereksinim duymamızın nedeni budur:
karaktersayisi=`echo -n "$1" | wc -c | sed 's/ //g' `
# şimdi son karakteri elde et
rval=`echo -n "$1" | cut -b $karaktersayisi`
}
kes()
{
# verilen bir katarın son karakterini kesip, geriye kalanı
# $rval içine yerleştirir
if [ -z "$1" ]; then
# boş katar
rval=""
return
fi
# wc, çıktının sonuna biraz boşluk koymaktadır, sed'e gereksinim
# duymamızın nedeni budur:
karaktersayisi=`echo -n "$1" | wc -c | sed 's/ //g' `
if [ "$karaktersayisi" = "1" ]; then
# katarda sadece bir karakter var
rval=""
return
fi
karaktersayisieksi1=`expr $karaktersayisi "-" 1`
# son hariç hepsini al:
rval=`echo -n "$1" | cut -b 0-${karaktersayisieksi1}`
}
while [ -n "$1" ]; do
case $1 in
-h) yardim;shift 1;; # yardım fonksiyonu çağırıldı
--) shift;break;; # seçeneklerin sonu
-*) hata "hata: böyle bir seçenek yok. Yrdım için $1. -h ";;
*) break;;
esac
done
# Programın ana kısmı
toplam=0
agirlik=1
# bir parametre mutlaka verilmelidir:
[ -z "$1" ] && yardim
ikilisayi="$1"
orjikilisayi="$1"
while [ -n "$ikilisayi" ]; do
sonkarakter "$ikilisayi"
if [ "$rval" = "1" ]; then
toplam=`expr "$agirlik" "+" "$toplam"`
fi
# $ikilisayi'daki son karakteri çıkart
kes "$ikilisayi"
ikilisayi="$rval"
agirlik=`expr "$agirlik" "*" 2`
done
echo "İkili sayı sistemindeki $orjikilisayi nın
onlu sayı sistemindeki değeri $toplam dır"
Kullanılan algoritma, sağ taraftan başlayarak, her basamaktaki sayının
ağırlığını (1,2,4,8,16,..) kullanarak, eğer ilgili basamaktaki sayı 1 ise,
toplam değişkenine eklemektedir. Sözgelimi "10", 0 * 1 + 1 * 2 = 2 dir.
#!/bin/sh
# vim: set sw=4 ts=4 et:
surum="0.1"
yardim()
{
cat <<YARDIM
rotatefile -- dosya adını çevirir
KULLANIM: rotatefile [-h] dosyaadi
SEÇENEKLER: -h yardim metin
ÖRNEK: rotatefile giden
Bu program giden.2 yi giden.3, giden.1 i giden.2, giden i giden.1 olarak
değiştirerek boş bir giden dosyası yaratacaktır
En fazla 10'a kadar değiştirmektedir.
sürüm $surum
YARDIM
exit 0
}
hata()
{
echo "$1"
exit 1
}
while [ -n "$1" ]; do
case $1 in
-h) yardim;shift 1;;
--) break;;
-*) echo "hata: böyle bir seçenek yoktur $1. Yardım için -h";exit 1;;
*) break;;
esac
done
# girilen verileri denetleme:
if [ -z "$1" ] ; then
error "HATA: parametre olarak dosya vermeniz gerekmektedir,
yardım için -h kullanınız"
fi
dosyan="$1"
# .1 , .2 vs. dosyalrını adını değiştir:
for n in 9 8 7 6 5 4 3 2 1; do
if [ -f "$dosyan.$n" ]; then
p=`expr $n + 1`
echo "mv $dosyan.$n $dosyan.$p"
mv $dosyan.$n $dosyan.$p
fi
done
# orijinal dosyayı:
if [ -f "$dosyan" ]; then
echo "mv $dosyan $dosyan.1"
mv $dosyan $dosyan.1
fi
echo touch $ya
touch $dosyan
Bu nasıl çalışmaktadır? Kullanıcının parametre olarak dosya verdiğini
denetledikten sonra, program, 9'dan 1'e doğru bir döngü içerisine
girmektedir. Dolayısıyla, 9. dosya 10, 8. dosya 9 vs. olmaktadır.
Döngü bittikten sonra, orijinal dosyayi 1 olarak adını değiştirdikten sonra
orijinal dosya adında boş bir dosya yaratılmaktadır.
sh -x garipbetikkullanarak bulabilirsiniz.
sh -n sizin_programinizEğer, sonuçta hiç bir şey görüntülenmiyorsa, yazılım hatası yok demektir.
|
|
Görselyöre sayfalarının bakımı, LinuxFocus Editörleri tarafından yapılmaktadır
© Katja and Guido Socher, FDL LinuxFocus.org Burayı klikleyerek hataları rapor edebilir ya da yorumlarınızı LinuxFocus'a gönderebilirsiniz |
Çeviri bilgisi:
|
2001-09-17, generated by lfparser version 2.17