Bash'te değişken tanımlamak için ad=değer yazarsınız; eşittir işaretinin iki yanında boşluk olmamalıdır. Değeri okumak için adın önüne dolar işareti koyarsınız: $ad ya da ${ad}. Bir değişkeni alt süreçlere aktarmak için export, tamamen silmek için unset, değiştirilemez yapmak için readonly kullanılır.
Kural kısa görünse de pratikte en çok hata bu konuda yapılır: eşittir çevresindeki bir boşluk atamayı komut çağrısına çevirir, tırnaksız bir değişken birden fazla kelimeye bölünür, süslü parantez unutulduğunda kabuk başka bir değişken adı okur. Bu yazıda bu ayrıntıları kılavuzdaki kurallarla ve çalıştırılmış örneklerle ele alıyoruz. Serinin diğer konuları için Bash öğrenme rehberi sayfasına bakabilirsiniz.
Parametre ve değişken: kılavuz ne diyor?

Kılavuz, değer saklayan her şeye parametre der. Parametre bir ad, bir sayı veya özel bir karakter olabilir. Bir adla gösterilen parametreye değişken denir. Bir değişkenin bir değeri ve sıfır ya da daha fazla niteliği (attribute) vardır; nitelikler declare komutuyla verilir, export ve readonly ise belirli nitelikleri atar. Sayılarla gösterilen parametreler ($1, $2) konumsal parametrelerdir ve argümanlar yazısında anlatılır.
Bir değişken kendisine bir değer atandığında tanımlı (set) sayılır. Boş dizge de geçerli bir değerdir; yani v= yazdığınızda v tanımlıdır ama değeri boştur. Tanımlı bir değişkeni tanımsız hale getirmenin tek yolu unset komutudur. Bu ayrım, varsayılan değer genişletmelerinde ve set -u seçeneğinde önem kazanır.
Değişken adı yalnızca harf, rakam ve alt çizgiden oluşmalı ve bir harf ya da alt çizgiyle başlamalıdır. Kılavuz bu tür kelimeye name (tanımlayıcı) der. 2ad veya ad-soyad geçerli ad değildir; bu biçimde bir atama yazarsanız kabuk satırı bir komut adı olarak yorumlar:
2ad=x
# çıktı: ornek.sh: line 1: 2ad=x: command not found
ad-soyad=x
# çıktı: ornek.sh: line 3: ad-soyad=x: command not found
ad_soyad="Ayşe Yılmaz"
echo "$ad_soyad"
# çıktı: Ayşe YılmazAtama kuralı: eşittir çevresinde boşluk yok
Atama ifadesinin biçimi ad=[değer] şeklindedir. Kabuk bir satırı önce kelimelere ve operatörlere ayırır; ad = "Ayşe" yazdığınızda ortaya üç kelime çıkar ve ilk kelime olan ad bir komut adı sayılır. Böyle bir komut olmadığı için "command not found" hatası alırsınız ve çıkış durumu 127 olur.
ad = "Ayşe"
# çıktı: ornek.sh: line 1: ad: command not found
# $? = 127
ad="Ayşe"
echo "$ad"
# çıktı: AyşeBenzer bir hata, atamanın sol tarafına dolar işareti koymaktır. $ad=Mehmet yazdığınızda kabuk önce $ad değerini genişletir ve ortaya Ayşe=Mehmet diye bir kelime çıkar. Genişletmeyle oluşan bu kelime bir atama olarak tanınmaz; kabuk onu çalıştırılacak bir komut adı sayar:
ad="Ayşe"
$ad=Mehmet
# çıktı: ornek.sh: line 2: Ayşe=Mehmet: command not found
ad=Mehmet
echo "$ad"
# çıktı: MehmetDeğer verilmezse değişkene boş dizge atanır. Değer kısmı tilde genişletmesi, parametre genişletmesi, komut ikamesi, aritmetik genişletme ve tırnak kaldırma işlemlerinden geçer. Kılavuz, atamalarda kelime bölme ve dosya adı genişletmesinin yapılmadığını özellikle belirtir. Bu yüzden b=$a ataması, a içinde birden fazla boşluk olsa bile değeri olduğu gibi kopyalar ve desen=*.txt ataması yıldızı genişletmez. Genişletme, değişkeni tırnaksız kullandığınız anda gerçekleşir:
touch a.txt b.txt
a="bir iki"
b=$a
desen=*.txt
echo "$b"
# çıktı: bir iki
echo $b
# çıktı: bir iki
echo "$desen"
# çıktı: *.txt
echo $desen
# çıktı: a.txt b.txtTırnaksız $b, kelime bölmeden geçtiği için iki ayrı argümana dönüşür ve echo bunları tek boşlukla birleştirir. Tırnaksız $desen ise dosya adı genişletmesinden geçer ve klasördeki eşleşen dosyaların listesine dönüşür. Kural basittir: değişkeni kullanırken, bölünmesini özellikle istemediğiniz sürece çift tırnak içine alın. Tırnaklamanın bütün ayrıntıları tek tırnak ve çift tırnak yazısında anlatılıyor.
$var ile ${var} arasındaki fark
Kılavuza göre süslü parantez çoğu zaman isteğe bağlıdır; görevi, değişken adını hemen arkasından gelen ve adın parçası sanılabilecek karakterlerden ayırmaktır. Alt çizgi, harf ve rakamlar ad karakteri olduğu için "$dosya_2024.txt" ifadesinde kabuk dosya_2024 adında bir değişken arar. Böyle bir değişken yoksa yerine boş dizge gelir:
dosya="rapor"
echo "$dosya_2024.txt"
# çıktı: .txt
echo "${dosya}_2024.txt"
# çıktı: rapor_2024.txtSüslü parantez iki durumda zorunludur: dokuzdan büyük konumsal parametrelerde (${10}) ve adın ardından ad karakteri geldiğinde. Ayrıca ${#ad}, ${ad:-varsayılan} veya ${ad/a/b} gibi bütün gelişmiş genişletmeler süslü parantezle yazılır. Bu genişletmeler varsayılan değer ve string işlemleri yazılarında anlatılıyor.
Bash değişkenlerinde tip yoktur

Bir değişkenin değeri varsayılan olarak bir metin dizgesidir. a=5 ataması bir sayı değil, "5" karakterini saklar. Bu yüzden echo $a+$b toplama yapmaz, iki değeri araya artı işareti koyarak yazar. Aritmetik işlem için $(( )) kullanılır ya da değişkene declare -i ile tamsayı niteliği verilir. Kılavuza göre tamsayı niteliği olan bir değişkene yapılan atamada değer, $(( )) yazılmasa bile aritmetik ifade olarak değerlendirilir.
a=5; b=3
echo $a+$b
# çıktı: 5+3
echo $((a + b))
# çıktı: 8
declare -i t
t=a+b
echo "$t"
# çıktı: 8Aritmetiğin kuralları (tamsayı sınırı, taban gösterimi, operatörler) aritmetik işlemler yazısında, nitelikler ise declare ve readonly yazısında ayrıntılı ele alınıyor.
+= ile ekleme
+= operatörü değişkenin mevcut değerine ekleme yapar. Dizge değerli bir değişkende sağdaki değer genişletilir ve sona eklenir. Tamsayı niteliği olan bir değişkende ise iki taraf da aritmetik olarak değerlendirilir ve toplam atanır. Dizi değişkenlerde += yeni elemanları sona ekler; bu kullanım dizi yazısında anlatılıyor.
s="abc"
s+="def"
echo "$s"
# çıktı: abcdef
declare -i n=5
n+=3
echo "$n"
# çıktı: 8
yol="/usr/bin"
yol+=":/opt/araclar/bin"
echo "$yol"
# çıktı: /usr/bin:/opt/araclar/binexport: değişkeni alt süreçlere aktarmak
Kabukta tanımladığınız bir değişken varsayılan olarak yalnızca o kabuğa aittir; kabuğun başlattığı programlar onu görmez. Bir programa çalışırken verilen ad=değer çiftleri listesine kılavuz ortam (environment) der. export ad komutu değişkeni dışa aktarılacak olarak işaretler; bundan sonra başlatılan her komut, ortamında bu değişkeni bulur. Kabuk başlarken de kendi ortamındaki her ad için bir değişken oluşturur ve onu otomatik olarak dışa aktarılmış sayar; PATH ve HOME gibi değişkenler bu yüzden betiklerinizde hazır bulunur.
yerel=1
export ortak=2
bash -c 'echo "yerel=[$yerel] ortak=[$ortak]"'
# çıktı: yerel=[] ortak=[2]
SELAM=merhaba bash -c 'echo "çocuk: $SELAM"'
# çıktı: çocuk: merhaba
echo "ana: [${SELAM-}]"
# çıktı: ana: []İkinci kullanım çok işe yarar: bir komutun önüne AD=değer yazdığınızda kılavuza göre bu atama yalnızca o komutun ortamına girer ve komut çalıştığı sürece geçerli olur. Kabuğun kendi değişkeni değişmez. export -n ad dışa aktarma işaretini kaldırır, export -p dışa aktarılan değişkenleri yeniden kullanılabilir biçimde listeler. Dışa aktarma tek yönlüdür: alt süreç kendi kopyasını değiştirse bile üst kabuktaki değer değişmez; bu konu subshell yazısında anlatılıyor.
PATH="./yok"
printf 'b\na\n' | sort
# çıktı: ornek.sh: line 2: sort: command not foundAtama kabul eden komutlar ve set -a
Kılavuz, atama ifadelerinin bazı yerleşik komutlara argüman olarak da verilebildiğini belirtir: alias, declare, typeset, export, readonly ve local. Bunlara bildirim komutları (declaration commands) denir. export AD=deger veya local sayac=0 yazabilmenizin nedeni budur; bu komutlarda eşittirin sağındaki değer, sıradan bir atamadaki gibi işlenir.
Bir grup değişkeni tek tek export etmek yerine set -a seçeneğini kullanabilirsiniz. Kılavuza göre bu seçenek açıkken oluşturulan veya değiştirilen her değişken ve fonksiyon dışa aktarma niteliği alır. Bir ayar dosyasını source ile okurken dosyadaki bütün değişkenlerin alt süreçlere geçmesini istiyorsanız dosyayı set -a ile set +a arasında okumak yaygın bir yöntemdir. export -n ise işareti kaldırır ama değişkeni silmez:
set -a
renk=mavi
set +a
bash -c 'echo "renk=$renk"'
# çıktı: renk=mavi
export -n renk
bash -c 'echo "renk=[$renk]"'
# çıktı: renk=[]
echo "kabukta hâlâ: $renk"
# çıktı: kabukta hâlâ: maviFonksiyonlar içinde bir değişkenin başka bir değişkene ad referansı (nameref) olmasını sağlayan declare -n niteliği de bu bölümde tanımlanır: referans değişkene yapılan her atama, adı verilen asıl değişkene yapılır. Bu yöntem bir fonksiyondan sonuç döndürmenin temiz bir yoludur ve local ve kapsam yazısında örnekleriyle anlatılıyor.
unset ve readonly
unset ad, değişkeni tamamen kaldırır ve ortamdan da siler. Kılavuza göre seçenek verilmezse ad önce değişken olarak aranır; o adda bir değişken yoksa aynı adlı bir fonksiyon silinir. Bu belirsizliği önlemek için değişkenler için unset -v, fonksiyonlar için unset -f yazabilirsiniz. Boş atama ile unset farklı sonuç verir: v= değişkeni boş ama tanımlı bırakır, unset v tanımsız yapar. [[ -v v ]] testi bu farkı görmenizi sağlar:
v=
[[ -v v ]] && echo "v tanımlı (değeri boş)"
# çıktı: v tanımlı (değeri boş)
unset v
[[ -v v ]] || echo "v artık tanımsız"
# çıktı: v artık tanımsız
echo "[${v-tanımsız}]"
# çıktı: [tanımsız]readonly bir değişkeni salt okunur yapar: değeri sonradan atamayla değiştirilemez ve unset ile silinemez. Kılavuz, readonly ad=değer biçimiyle değerin aynı anda atanabileceğini belirtir. Salt okunur bir değişkene atama denemesi bir hata mesajı üretir:
readonly SURUM="1.4"
SURUM="2.0"
# çıktı: ornek.sh: line 2: SURUM: readonly variable
unset SURUM
# çıktı: ornek.sh: line 4: unset: SURUM: cannot unset: readonly variable
echo "$SURUM"
# çıktı: 1.4Bu örnekte betik hatalardan sonra çalışmaya devam etti. Kılavuzun POSIX modu listesine göre, POSIX modunda etkileşimsiz bir kabuk, komut adı olmayan bir atamada salt okunur değişken hatası oluşursa çıkar; varsayılan modda ise yalnızca o komut başarısız olur. Sabit değerler için readonly kullanmak, bir yazım hatasının değeri sessizce değiştirmesini önler.
Değişkenleri incelemek: declare -p
Bir değişkenin değerini ve niteliklerini birlikte görmek için declare -p ad kullanılır. Çıktı, kabuğa yeniden verildiğinde aynı değişkeni oluşturacak biçimdedir. -x dışa aktarılmış, -i tamsayı, -r salt okunur, -- ise niteliksiz bir değişkeni gösterir:
declare -i n=8
s="abcdef"
export ortak=2
readonly SABIT=1
declare -p n s ortak SABIT
# çıktı:
# declare -i n="8"
# declare -- s="abcdef"
# declare -x ortak="2"
# declare -r SABIT="1"Küçük bir uygulama: ayarları değişkenlerle yönetmek
Aşağıdaki örnek önce küçük bir ayar.sh betiği oluşturur. Bu betik varsayılan değerleri değişkenlerde tutar, ortamdan gelen bir değerin varsayılanı ezmesine izin verir ve bir dosya adını parçalardan oluşturur. Süslü parantez, tırnaklama, += ve ortam önekiyle çağırma aynı örnekte bir araya geliyor:
printf '%s\n' 'hedef="${HEDEF:-yedekler}"' 'ad="site"' 'ek="2026_11"' \
'dosya="${hedef}/${ad}_${ek}.tar"' 'mesaj="Hedef: $hedef"' 'mesaj+=", dosya: $dosya"' \
'echo "$mesaj"' > ayar.sh
bash ayar.sh
# çıktı: Hedef: yedekler, dosya: yedekler/site_2026_11.tar
HEDEF=/srv/arsiv bash ayar.sh
# çıktı: Hedef: /srv/arsiv, dosya: /srv/arsiv/site_2026_11.tarBetik içinde HEDEF ortam değişkeni varsa onun değeri, yoksa "yedekler" kullanılır. İkinci çağrıda HEDEF=/srv/arsiv öneki yalnızca o çalıştırma için geçerlidir. Değişken adlarını süslü parantezle ayırmak, $ad_ gibi istenmeyen ad okumalarını önler. Gerçek bir betikte ek değerini bir komutla üretebilirsiniz; bunun için komut ikamesi yazısına bakın.
Sık yapılan hatalar

- Eşittir çevresinde boşluk:
ad = değerbir atama değil,adadlı komutun çağrısıdır. - Sol tarafa dolar işareti koymak:
$ad=değerönce genişletilir ve bir komut adına dönüşür. - Değişkeni tırnaksız kullanmak:
$dosyaboşluk veya joker karakter içeriyorsa birden fazla argümana dönüşür."$dosya"yazın. - Süslü parantezi unutmak:
"$ad_yedek",addeğilad_yedekdeğişkenini okur. - Büyük harfli sistem değişkenlerini ezmek:
PATH,IFS,HOMEgibi adları kendi verileriniz için kullanmayın. - Betikteki export komutunun terminali etkilemesini beklemek: Betik ayrı bir süreçtir; değişkeni mevcut kabuğa almak için dosyayı
sourceile çalıştırın.
Sık Sorulan Sorular
Bash değişkenine boşluklu bir değer nasıl atanır?
Değeri tırnak içine alın: mesaj="Merhaba dünya". Tırnaksız yazarsanız kabuk ilk boşlukta kelimeyi böler ve dünya kelimesini çalıştırılacak bir komut olarak görür; ilk kısım ise yalnızca o komut için geçerli bir ortam ataması olur.
export ile normal değişken arasındaki fark nedir?
Normal değişken yalnızca tanımlandığı kabukta görünür. export ile işaretlenen değişken, o kabuğun başlattığı bütün komutların ortamına kopyalanır. Kopya olduğu için alt süreçteki değişiklikler üst kabuğa geri dönmez.
Boş değişken ile tanımsız değişken aynı şey mi?
Hayır. v= değişkeni boş değerle tanımlar; unset v ise tamamen kaldırır. ${v-x} yalnızca tanımsızlıkta, ${v:-x} hem tanımsızlıkta hem boşlukta varsayılan değeri kullanır. set -u açıkken tanımsız bir değişkeni okumak hata verir, boş bir değişkeni okumak vermez.
Bir değişkenin tanımlı olup olmadığını nasıl anlarım?
[[ -v ad ]] testi, değişken tanımlıysa (boş değerli olsa bile) doğru döner. Değerin boş olup olmadığını ayrıca denetlemek için [[ -n $ad ]] kullanılır. İkisini birlikte kullanarak "hiç verilmemiş" ile "boş verilmiş" durumlarını ayırt edebilirsiniz.
Fonksiyon içindeki değişken dışarıyı etkiler mi?
Evet, Bash'te değişkenler varsayılan olarak geneldir; fonksiyon içinde yapılan atama fonksiyon dışındaki aynı adlı değişkeni değiştirir. Bunu önlemek için local kullanılır. Ayrıntılar local değişken ve kapsam yazısında.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: Bash öğrenme rehberi · Tırnak farkı · declare ve readonly · Varsayılan değer · local ve kapsam