10 - Kabuk Programlama
2025
bash
(Bourne Again Shell) - Derslerimizde genellikle bunu kullanıyoruz.sh
(Bourne Shell)ksh
(Korn Shell)zsh
(Z Shell)fish
(Friendly Interactive Shell)Gündelik hayatta terminalde yazdığımız ls
, cd
, mkdir
gibi komutları kabuk çalıştırır.
Düşünün: Her sabah bilgisayarınızı açtığınızda belirli klasörleri yedeklemek, geçici dosyaları silmek ve bir uygulama başlatmak istiyorsunuz. Bunları her gün elle yapmak yerine bir kabuk betiği yazarak tek komutla halledebilirsiniz!
Her programlama dilinde olduğu gibi, “Merhaba Dünya” ile başlayalım!
nano
, vim
, gedit
).merhaba.sh
olarak kaydedin:#!/bin/bash
: Shebang olarak bilinir. Betiğin hangi yorumlayıcı (interpreter) ile çalıştırılacağını belirtir. Burada bash
kabuğunu kullanacağımızı söylüyoruz.# Bu benim ilk kabuk betiğim
: #
ile başlayan satırlar yorum satırlarıdır. Kabuk tarafından göz ardı edilir, kodu açıklamak için kullanılır.echo "Merhaba Dünya!"
: Ekrana “Merhaba Dünya!” yazdıran komut.Oluşturduğumuz merhaba.sh
dosyasını çalıştırmak için iki adımımız var:
Çalıştırma İzni Vermek: Dosyaya çalıştırma (execute) izni vermemiz gerekir. Terminalde:
chmod
: Dosya izinlerini değiştiren komut.+x
: Çalıştırma izni ekle.Betiği Çalıştırmak: Terminalde, betiğin bulunduğu dizindeyken:
./
: “Mevcut dizindeki” anlamına gelir. Güvenlik nedeniyle, sistem genellikle doğrudan merhaba.sh
yazarak çalıştırmanıza izin vermez (PATH’de değilse).Alıştırma 1: Kendi adınızı ve soyadınızı ekrana yazdıran adim.sh
adında bir betik oluşturun, çalıştırma izni verin ve çalıştırın.
#
karakteri ile başlayan her şey o satırın sonuna kadar yorum olarak kabul edilir.#!/bin/bash
# Bu bir yorum satırıdır
# Bu da başka bir yorum
# Bu betik, sistemdeki kullanıcı sayısını gösterir (aslında göstermez, sadece örnektir)
echo "Yorumları anladık mı?" # Bu da satır sonu yorumu
Gelecekte kendi kodunuzu (veya başkasının kodunu) okurken yorumlar hayat kurtarır!
Değişken Tanımlama:
Önemli Kurallar:
=
arasında ve =
ile değer arasında boşluk olmamalıdır._
) ile başlamalıdır. Sayı içerebilir ama sayı ile başlayamaz.#!/bin/bash
AD="Ahmet"
SOYAD="Yılmaz"
YAS=30
echo "Adım: $AD"
echo "Soyadım: $SOYAD"
echo "Yaşım: $YAS"
Değişkenin değerini kullanmak için başına $
işareti koyarız: $AD
, $YAS
.
Kabuk programlamada tırnak işaretleri çok önemlidir ve farklı anlamlara gelir:
"..."
):
$degisken
) ve komut yerine koyma ($(komut)
) işlenir (genişletilir).'...'
):
`...`
) veya $(...)
(Komut Yerine Koyma):
$(...)
kullanımı daha modern ve iç içe kullanıma daha uygundur.Alıştırma 2: kullanici_bilgisi.sh
adında bir betik yazın.
KULLANICI_ADI
adında bir değişken tanımlayın ve kendi kullanıcı adınızı atayın.CALISMA_DIZINI
adında bir değişken tanımlayın ve pwd
komutunun çıktısını atayın.read
Komuturead
komutu bu iş için kullanılır. Kullanıcının girdiği değeri bir değişkene atar.Alıştırma 3: Kullanıcıdan iki sayı girmesini isteyen ve bu sayıları ekrana “Girdiğiniz sayılar: [sayi1] ve [sayi2]” formatında yazdıran sayi_al.sh
adında bir betik yazın.
$0
: Betiğin kendi adı.$1
: Birinci argüman.$2
: İkinci argüman.$9
: Dokuzuncu argüman. (10 ve sonrası için ${10}
şeklinde kullanılır)$#
: Betiğe geçirilen toplam argüman sayısı.$*
: Tüm argümanları tek bir string olarak verir (tırnak içinde kullanıldığında).$@
: Tüm argümanları ayrı ayrı stringler olarak verir (tırnak içinde kullanıldığında genellikle daha güvenlidir).Örnek (parametreler.sh
):
#!/bin/bash
echo "Betiğin adı: $0"
echo "İlk argüman: $1"
echo "İkinci argüman: $2"
echo "Toplam argüman sayısı: $#"
echo "Tüm argümanlar (\$*): $*"
echo "Tüm argümanlar (\$@): $@"
Çalıştırma:
Çıktı:
Betiğin adı: ./parametreler.sh
İlk argüman: merhaba
İkinci argüman: dünya
Toplam argüman sayısı: 3
Tüm argümanlar ($*): merhaba dünya 123
Tüm argümanlar ($@): merhaba dünya 123
Alıştırma 4: selamla.sh
adında bir betik yazın. Bu betik, komut satırından bir isim argümanı alacak ve “Merhaba, [isim]!” mesajını yazdıracak. Eğer isim verilmezse, “Lütfen bir isim giriniz.” mesajı versin. (İpucu: $#
kontrolü yapabilirsiniz.)
Kabukta aritmetik işlemler için birkaç yöntem vardır:
let
Komutu:
$((...))
Yapısı (Önerilen): Bu yapı daha modern ve esnektir.
SAYI1=10
SAYI2=5
TOPLAM=$((SAYI1 + SAYI2))
FARK=$((SAYI1 - SAYI2))
CARPIM=$((SAYI1 * SAYI2)) # Çarpma için *
BOLUM=$((SAYI1 / SAYI2)) # Bölme için /
MOD=$((SAYI1 % SAYI2)) # Modülüs (kalan) için %
echo "Toplam: $TOPLAM"
echo "Fark: $FARK"
echo "Çarpım: $CARPIM"
echo "Bölüm: $BOLUM"
echo "Mod: $MOD"
# Artırma/Azaltma
X=5
X=$((X + 1)) # veya ((X++)) bash'e özgü
echo "X: $X" # X: 6
Alıştırma 5: Kullanıcıdan iki sayı alan ve bu sayıların toplamını, farkını, çarpımını ve bölümünü ekrana yazdıran hesap_makinesi.sh
adında bir betik yazın.
if
, else
, elif
Program akışını belirli koşullara göre değiştirmek için kullanılır.
Temel yapı:
else
ve elif
(else if) ile genişletilebilir:
if [ koşul1 ]; then
# koşul1 doğruysa
elif [ koşul2 ]; then
# koşul1 yanlış, koşul2 doğruysa
else
# hiçbir koşul doğru değilse
fi
ÖNEMLİ: [
(test komutunun takma adı) ile koşul arasında ve koşul ile ]
arasında boşluk olmalıdır! Yani [ $SAYI -eq 10 ]
doğru, [$SAYI -eq 10]
yanlış.
if
yapısı içindeki [ koşul ]
(veya test koşul
) bölümünde çeşitli karşılaştırmalar yapabiliriz:
1. Sayısal Karşılaştırmalar:
-eq
: Eşit (equal)-ne
: Eşit değil (not equal)-gt
: Büyük (greater than)-ge
: Büyük veya eşit (greater or equal)-lt
: Küçük (less than)-le
: Küçük veya eşit (less or equal)2. String Karşılaştırmalar:
=
: Eşit (Bazı kabuklarda ==
de çalışır, =
daha taşınabilirdir)!=
: Eşit değil-z string
: String boş mu? (zero length)-n string
: String boş değil mi? (non-zero length)3. Dosya Testleri:
-e dosya_yolu
: Dosya/Dizin var mı? (exists)-f dosya_yolu
: Dosya var ve normal bir dosya mı? (file)-d dosya_yolu
: Dizin var mı? (directory)-r dosya_yolu
: Okuma izni var mı? (readable)-w dosya_yolu
: Yazma izni var mı? (writable)-x dosya_yolu
: Çalıştırma izni var mı? (executable)-s dosya_yolu
: Dosya var ve boyutu sıfırdan büyük mü? (size)#!/bin/bash
read -p "Lütfen bir sayı giriniz: " SAYI
if [ -z "$SAYI" ]; then
echo "Bir sayı girmediniz!"
elif ! [[ "$SAYI" =~ ^[0-9]+$ ]]; then # Sadece sayı girildiğinden emin olalım (regex)
echo "Lütfen geçerli bir sayı giriniz."
elif [ $SAYI -lt 0 ]; then
echo "Girdiğiniz sayı negatif."
elif [ $SAYI -eq 0 ]; then
echo "Girdiğiniz sayı sıfır."
elif [ $SAYI -gt 0 ] && [ $SAYI -le 100 ]; then # && (VE) operatörü
echo "Girdiğiniz sayı 0 ile 100 arasında (0 hariç)."
else
echo "Girdiğiniz sayı 100'den büyük veya negatif olmayan bir sayı."
fi
&&
: VE (AND) operatörü. [ koşul1 ] && [ koşul2 ]
veya [ koşul1 -a koşul2 ]
(eski stil)||
: VEYA (OR) operatörü. [ koşul1 ] || [ koşul2 ]
veya [ koşul1 -o koşul2 ]
(eski stil)!
: DEĞİL (NOT) operatörü. ! [ koşul ]
Alıştırma 6:
Komut satırından bir dosya veya dizin adı alan bir betik (dosya_kontrol.sh
) yazın.
for
Döngüsü1. Liste Üzerinde Gezinme:
#!/bin/bash
echo "Meyveler:"
for MEYVE in elma armut çilek muz; do
echo " - $MEYVE"
done
echo
echo "Sayılar:"
for SAYI in 1 2 3 4 5; do
echo "Sayı: $SAYI"
done
# Komut çıktısı üzerinde gezinme
echo
echo "Geçerli dizindeki .txt dosyaları:"
for DOSYA in $(ls *.txt); do # veya for DOSYA in *.txt (daha iyi)
echo "Bulunan dosya: $DOSYA"
done
2. C-Stili for
Döngüsü (bash’e özgü):
while
Döngüsü#!/bin/bash
SAYAC=1
LIMIT=5
echo "While döngüsü:"
while [ $SAYAC -le $LIMIT ]; do
echo "Sayaç: $SAYAC"
SAYAC=$((SAYAC + 1)) # Sayacı artırmayı unutmayın, yoksa sonsuz döngü!
done
# Kullanıcı 'çıkış' yazana kadar girdi alma
GIRIS=""
while [ "$GIRIS" != "çıkış" ]; do
read -p "Bir komut girin (çıkmak için 'çıkış' yazın): " GIRIS
echo "Girdiğiniz: $GIRIS"
done
echo "Program sonlandırıldı."
Alıştırma 7:
for
döngüsü yazın (kareler_for.sh
).pozitif_sayi_while.sh
). Kullanıcı negatif bir sayı veya sıfır girdiği sürece tekrar sayı istesin. Pozitif sayı girildiğinde “Teşekkürler, pozitif bir sayı girdiniz: [SAYI]” mesajını versin. (Bir while
döngüsü kullanın).Tanımlama:
fonksiyon_adi() {
# komutlar
# yerel değişkenler tanımlanabilir: local degisken_adi="deger"
# parametrelere $1, $2, ... ile erişilir (fonksiyona özel)
# return ile sayısal bir çıkış durumu döndürülebilir (0-255)
}
veya
Çağırma:
Alıştırma 8:
İki sayıyı parametre olarak alan ve bu sayıların toplamını ekrana yazdıran topla
adında bir fonksiyon yazın. Betiğinizde bu fonksiyonu farklı sayılarla birkaç kez çağırın (fonksiyonlu_toplama.sh
).
$?
0
: Başarılı.0
dışında bir değer (genellikle 1-255): Hata oluştu.$?
özel değişkeninde saklanır.#!/bin/bash
ls /root # Bu komut normal kullanıcı için hata verecektir (izin yok)
echo "ls komutunun çıkış durumu: $?" # Muhtemelen 1 veya 2
mkdir test_dizini
echo "mkdir komutunun çıkış durumu: $?" # Başarılıysa 0
rmdir test_dizini
echo "rmdir komutunun çıkış durumu: $?" # Başarılıysa 0
# Betik sonunda çıkış durumu belirleme: exit komutu
if [ -f "onemli_dosya.txt" ]; then
echo "Dosya bulundu."
exit 0 # Başarılı çıkış
else
echo "HATA: onemli_dosya.txt bulunamadı!"
exit 1 # Hatalı çıkış
fi
Çıkış durumları, betiklerin birbirleriyle veya sistemle iletişim kurması için önemlidir.
yedekle.sh
):
tar
komutu ile sıkıştırarak (örn: kaynak_YYYY-AA-GG.tar.gz
formatında bir isimle) hedef klasöre kopyalasın.