original in en Katja and Guido Socher
en to tr Ceyhun ELMAS ve Erdal MUTLU
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
#!/bin/shThe #! 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 -ldosya.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 " $eiletidiziniBu 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 doneYukarı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 doneBu ş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 $dosyanBu 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.