Bash'te ekrana yazı basmanın iki yerleşik yolu vardır: echo argümanlarını aralarına boşluk koyup sonuna yeni satır ekleyerek yazar; printf ise bir biçim dizgesine göre çıktı üretir ve kendiliğinden yeni satır eklemez. Kısa ve sabit mesajlar için echo yeterlidir; değişken içerik, hizalı tablo, sayı biçimlendirme veya taşınabilir davranış gerektiğinde printf kullanmak daha güvenlidir.
Bu yazıda echo komutunun -n, -e ve -E seçeneklerini, printf biçim belirteçlerini, Bash'e özgü %b, %q ve %(...)T biçimlerini ve çıktıyı bir değişkene yazan printf -v seçeneğini örneklerle anlatıyoruz. Serinin diğer konuları için Bash öğrenme rehberi sayfasına bakabilirsiniz.
echo: argümanları yaz, satırı bitir
Kılavuza göre echo, argümanlarını aralarına birer boşluk koyarak yazar ve sonuna yeni satır ekler; yazma hatası olmadıkça çıkış durumu 0'dır. Argümanları kelimelere ayıran kabuk olduğu için tırnaksız birden fazla boşluk tek boşluğa iner. -n seçeneği sondaki yeni satırı kaldırır:
echo Merhaba dünya
# çıktı: Merhaba dünya
echo "Merhaba dünya"
# çıktı: Merhaba dünya
echo -n "satır sonu yok"; echo " | devam"
# çıktı: satır sonu yok | devam-e seçeneği ters eğik çizgili kaçış dizilerini yorumlar; -E bu yorumu, varsayılan olarak yorumlayan sistemlerde bile kapatır. Bash'te varsayılan durum kaçışların yorumlanmamasıdır, bu yüzden -e vermezseniz \n iki karakter olarak yazılır. \c kaçışı ise kendisinden sonraki bütün çıktıyı, sondaki yeni satır dahil, bastırır:
echo 'bir\niki'
# çıktı: bir\niki
echo -e 'bir\niki'
# çıktı:
# bir
# iki
echo -e 'görünür\cgörünmez'; echo
# çıktı: görünürecho neden bazen sürpriz yapar?
echo komutunun iki zayıf noktası vardır. Birincisi, kılavuzun belirttiği gibi echo, -- argümanını seçeneklerin sonu olarak yorumlamaz. İkincisi, yazdırmak istediğiniz değer -n veya -e gibi bir seçeneğe benziyorsa echo onu seçenek olarak alır. Bir değişkenin değerini bilmiyorsanız echo "$v" beklediğinizi yazmayabilir:
v="-n"
echo "$v"; echo "(önceki komut hiçbir şey yazmadı)"
# çıktı: (önceki komut hiçbir şey yazmadı)
echo -- "$v"
# çıktı: -- -n
printf '%s\n' "$v"
# çıktı: -nÜçüncü bir ayrıntı, xpg_echo kabuk seçeneğidir. Kılavuza göre bu seçenek echo komutunun seçenekleri yorumlayıp yorumlamayacağını ve kaçış dizilerini genişletip genişletmeyeceğini belirler. Açıldığında -e yazmadan da kaçışlar çözülür; POSIX modunda ise echo hiçbir argümanı seçenek saymaz. Yani aynı echo satırı, kabuğun ayarlarına göre farklı çıktı verebilir:
shopt -s xpg_echo
echo 'bir\niki'
# çıktı:
# bir
# ikiprintf: biçim dizgesi ve argümanlar
printf komutunun biçimi printf [-v değişken] biçim [argümanlar] şeklindedir. Kılavuza göre biçim dizgesi üç tür öğe içerir: olduğu gibi kopyalanan düz karakterler, dönüştürülüp yazılan kaçış dizileri ve her biri sıradaki argümanı yazdıran biçim belirteçleri. printf sona yeni satır eklemez; satırı bitirmek için biçimin sonuna \n yazarsınız.
İki kural printf komutunu çok kullanışlı yapar. Biçim, bütün argümanlar tüketilene kadar yeniden kullanılır; böylece tek bir biçimle bir listenin her elemanını yazdırabilirsiniz. Biçimin istediğinden az argüman verilirse, eksik belirteçler sıfır veya boş dizge verilmiş gibi davranır:
printf '%s yaşında\n' 30
# çıktı: 30 yaşında
printf '%s\n' elma armut kiraz
# çıktı:
# elma
# armut
# kiraz
printf '%s=%s\n' renk mavi boyut 42
# çıktı:
# renk=mavi
# boyut=42
printf '[%s-%d]\n' x
# çıktı: [x-0]Sık kullanılan biçim belirteçleri

printf, C dilindeki printf(3) belirteçlerini (cCsSndiouxXeEfFgGaA) destekler. Belirtecin önüne bayrak, genişlik ve duyarlık ekleyebilirsiniz: %-8s sola dayalı 8 genişlikte bir dizge, %5d sağa dayalı 5 genişlikte bir tamsayı, %05d başı sıfırla doldurulmuş bir tamsayı, %.2f virgülden sonra iki basamaklı bir ondalık sayı yazar.
printf '|%-8s|%5d|\n' ad 42
# çıktı: |ad | 42|
printf '%05d %x %X %o\n' 42 255 255 8
# çıktı: 00042 ff FF 10
printf '%.2f %e\n' 3.14159 12345.678
# çıktı: 3.14 1.234568e+04
printf '%+d %+d %.3s\n' 5 -5 abcdef
# çıktı: +5 -5 abc
printf '%%%d tamamlandı\n' 80
# çıktı: %80 tamamlandı| Belirteç | Ne yazar | Örnek çıktı |
|---|---|---|
| %s | dizge | elma |
| %d, %i | işaretli tamsayı | 42 |
| %x, %X, %o | onaltılık, büyük harfli onaltılık, sekizlik | ff, FF, 10 |
| %f, %e | ondalık ve üstel gösterim | 3.14, 1.234568e+04 |
| %c | argümanın ilk karakteri | a |
| %b | argümandaki kaçışları çözerek dizge (Bash) | satır sonu üretir |
| %q | kabuğa yeniden verilebilir biçimde tırnaklı dizge (Bash) | dosya\ adı |
| %(biçim)T | tarih ve saat (Bash) | 1970-01-01 |
| %% | yüzde işareti | % |
Sayısal belirteçlere verilen argümanlar C dili sabitleri gibi yorumlanır; başta artı veya eksi işaretine izin verilir. Kılavuzdaki ilginç bir kurala göre argüman tek veya çift tırnakla başlıyorsa, değer tırnaktan sonraki karakterin sayısal kodudur. Böylece bir karakterin kodunu dış araç kullanmadan öğrenebilirsiniz. Sayı olmayan bir argüman ise hata verir; printf o belirteç için 0 yazar ve sıfırdan farklı bir durumla döner:
printf '%d %d\n' "'A" "'a"
# çıktı: 65 97
printf '%d\n' 0x1F 010
# çıktı:
# 31
# 8
printf '%d\n' abc
# çıktı:
# ornek.sh: line 7: printf: abc: invalid number
# 0
# $? = 1İkinci satırda 0x1F onaltılık, 010 ise başındaki sıfır yüzünden sekizlik olarak okundu ve 8 oldu. Kullanıcıdan gelen "010" gibi değerleri sayıya çevirirken bu davranışı hesaba katın; Bash aritmetiğindeki taban kuralları aritmetik işlemler yazısında anlatılıyor.
Türkçe karakterler ve genişlik

%-8s gibi bir genişlik verdiğinizde dolgunun karakter mi bayt mı hesaplandığı önemlidir. Kılavuza göre %b, %q ve %T belirteçleri genişlik ve duyarlığı bayt olarak uygular. Aynı bölüm Bash 5.3 için %s ve %c belirteçlerine l (long) değiştiricisinin eklenebildiğini, %ls biçiminin genişliği bayt yerine karakter olarak hesapladığını anlatır. 5.2.37 ile denediğimizde hem %-6s hem %-6ls genişliği bayt olarak hesapladı; Türkçe harfler UTF-8'de iki bayt tuttuğu için sütun kaydı:
printf '|%-6s|\n' ab ğü
# çıktı:
# |ab |
# |ğü |İkinci satırda "ğü" dört bayt olduğundan yalnızca iki boşlukla dolduruldu. Türkçe metinleri hizalamanız gerekiyorsa dolguyu kendiniz hesaplayabilirsiniz: UTF-8 yerel ayarında ${#metin} karakter sayısını verir, eksik kısmı printf '%*s' "$eksik" '' ile boşlukla tamamlayabilirsiniz. Kendi sisteminizdeki Bash sürümü 5.3 ise %ls biçimini deneyebilirsiniz.
%b ile %s farkı
%s argümanı olduğu gibi yazar. %b ise argümandaki ters eğik çizgili kaçışları, echo -e ile aynı şekilde çözer. Kaçış dizileri biçim dizgesinin kendisinde her zaman çözülür; %b, bu işlemi bir argümanın, örneğin bir değişkenin değeri üzerinde yapmanızı sağlar:
metin='bir\tiki\nüç'
printf '%s\n' "$metin"
# çıktı: bir\tiki\nüç
printf '%b\n' 'satır1\nsatır2'
# çıktı:
# satır1
# satır2%q: kabuğa yeniden verilebilir çıktı
%q belirteci argümanı, kabuğa girdi olarak verildiğinde aynı değeri üretecek biçimde tırnaklar. Kılavuza göre argüman gerektiriyorsa ANSI-C tırnaklama ($'...'), gerekmiyorsa ters eğik çizgi kullanılır. Bu, boşluk veya özel karakter içeren bir değeri günlüğe yazarken, başka bir kabukta çalışacak bir komut satırı oluştururken ya da değerin içinde görünmeyen karakter olup olmadığını anlamaya çalışırken çok işe yarar:
printf '%q\n' "dosya adı's" $'a\nb' 'düz'
# çıktı:
# dosya\ adı\'s
# $'a\nb'
# düz
deger=$'satır sonu\r'
printf 'görünen: [%s]\n' "${deger%$'\r'}"
# çıktı: görünen: [satır sonu]
printf 'gerçek: %q\n' "$deger"
# çıktı: gerçek: $'satır sonu\r'Son örnek, Windows'tan gelen bir dosyadan okunan değerlerin sonundaki görünmez satır başı karakterini %q ile nasıl fark edebileceğinizi gösteriyor. Bu karakterin yol açtığı hatalar sık hata mesajları yazısında ele alınıyor.
printf -v: çıktıyı değişkene yazmak
-v değişken seçeneği çıktıyı ekrana yazmak yerine verilen değişkene atar. Biçimlendirilmiş bir değeri bir değişkende saklamak için komut ikamesi ($(printf ...)) kullanmak yerine bu seçeneği tercih edebilirsiniz; ayrı bir alt kabuk açılmaz ve sondaki yeni satırlar silinmez:
printf -v no '%03d' 7
echo "dosya_$no.log"
# çıktı: dosya_007.log
printf -v cizgi '%*s' 10 ''
echo "[${cizgi// /-}]"
# çıktı: [----------]İkinci örnekte %*s genişliği argümandan alır: 10 karakterlik boşluk üretilir ve ardından parametre genişletmesiyle boşluklar tireye çevrilir. ${degisken// /-} biçimi string işlemleri yazısında anlatılıyor.
%(biçim)T: tarih ve saat
Bash'in printf komutu tarih ve saati harici bir program çağırmadan biçimlendirebilir. %(biçim)T belirtecindeki biçim, C kütüphanesindeki strftime biçimidir; argüman, Unix zamanının başlangıcından beri geçen saniye sayısıdır. Kılavuza göre -1 şimdiki zamanı, -2 kabuğun başlatıldığı zamanı temsil eder; argüman verilmezse şimdiki zaman kullanılır. Aşağıdaki örnek, sabit bir değerle sonucu görebilmeniz için 0 saniyeyi UTC saat diliminde biçimlendiriyor:
TZ=UTC printf '%(%Y-%m-%d %H:%M)T\n' 0
# çıktı: 1970-01-01 00:00Günlük satırlarının başına zaman damgası eklemek için printf '%(%F %T)T %s\n' -1 "mesaj" kalıbını kullanabilirsiniz. Bu durumda çıktı, çalıştırdığınız ana göre değişir.
Biçim dizgesindeki kaçış dizileri
Biçim dizgesindeki ters eğik çizgili kaçışlar printf tarafından her zaman çözülür; bu yüzden biçimi tek tırnakla yazmanız yeterlidir. \n, \t, \\ gibi yaygın kaçışların yanında onaltılık (\xHH), sekizlik ve Unicode (\uHHHH) kaçışlar da kullanılabilir. echo -e ile küçük bir fark vardır: kılavuz echo için sekizlik kaçışı \0nnn biçiminde, yani başında bir sıfırla tanımlar ve tanımadığı kaçışları olduğu gibi yazdığını belirtir:
printf '\x41\101ü\n'
# çıktı: AAü
echo -e '\0101 \x41'
# çıktı: A A
echo -e '\q bilinmeyen kaçış'
# çıktı: \q bilinmeyen kaçışBir argümanın içindeki kaçışların çözülmesini istiyorsanız yukarıda anlatılan %b belirtecini kullanın; %s argümanı olduğu gibi bırakır. Bu ayrım, kullanıcıdan gelen bir metni yazdırırken önemlidir: metinde \c gibi bir dizi varsa %b çıktının geri kalanını keser, %s ise metni harfi harfine yazar.
Kılavuzun POSIX modu listesinde printf ile ilgili bir madde daha vardır: POSIX modunda ondalık sayı belirteçlerine karşılık gelen argümanlar, varsa long double yerine double türüyle dönüştürülür; L uzunluk değiştiricisi long double kullanımını zorlar. Günlük betiklerde bu fark nadiren görünür, ama çok büyük veya çok hassas ondalık sayıları biçimlendirirken sonuçlar modlar arasında ayrışabilir. printf komutunun çıkış durumu başarıda sıfırdır; geçersiz bir seçenek, bir yazma hatası veya bir atama hatası olduğunda sıfırdan farklıdır.
Biçim dizgesine veri koymayın
printf komutunun ilk argümanı bir biçim dizgesidir ve içindeki % karakterleri belirteç olarak yorumlanır. Kullanıcıdan veya bir dosyadan gelen değeri doğrudan biçim yerine koyarsanız, değer yüzde işareti içerdiği anda çıktı bozulur:
veri='%s indirim %d'
printf "$veri\n"
# çıktı: indirim 0
printf '%s\n' "$veri"
# çıktı: %s indirim %dBirinci çağrıda %s boş dizgeye, %d sıfıra dönüştü ve çıktının başında bir boşluk kaldı. Doğru kullanım, biçimi sabit tutmak ve veriyi her zaman argüman olarak vermektir.
Uygulama: hizalı bir rapor
Biçimin yeniden kullanılması kuralı sayesinde, döngü yazmadan bir tablo üretebilirsiniz. Her satır için iki argüman tüketilir ve biçim baştan uygulanır. Başlık satırında da aynı genişlikleri kullanmak sütunları hizalı tutar:
printf '%-8s %6s\n' Meyve Adet
printf '%-8s %6d\n' elma 12 armut 7 kiraz 130
# çıktı:
# Meyve Adet
# elma 12
# armut 7
# kiraz 130echo mu printf mi?

| Durum | Önerilen |
|---|---|
| Sabit, kısa bir mesaj | echo |
| Değeri bilinmeyen bir değişkeni yazmak | printf '%s\n' |
| Sonunda yeni satır istemiyorsanız | printf veya echo -n |
| Kaçış dizileri (sekme, yeni satır) | printf |
| Hizalı sütunlar, sayı biçimi | printf |
| Sonucu bir değişkene yazmak | printf -v |
| Değeri kabuk için güvenli tırnaklamak | printf %q |
Sık yapılan hatalar
- printf sonrası yeni satırı unutmak:
printfsatırı kendiliğinden bitirmez; bir sonraki çıktı aynı satıra yazılır. - Değişkeni biçim dizgesi yapmak:
printf "$veri"yerineprintf '%s' "$veri"yazın. - echo ile seçenek benzeri değer yazmak:
-n,-egibi değerlerechotarafından seçenek sayılır. - echo -e sonucunu her yerde aynı sanmak:
xpg_echove POSIX moduechodavranışını değiştirir. - Başında sıfır olan sayılar:
printf '%d' 010sekizlik okunur ve 8 yazar;08ve09ise "invalid octal number" hatası verir. - Genişliğin karakter sayıldığını varsaymak: 5.2.37'de
%-10sdolguyu bayt olarak hesaplar ve Türkçe harfler sütunları kaydırır.
Sık Sorulan Sorular
echo ile printf arasındaki temel fark nedir?
echo argümanları boşlukla birleştirip yeni satır ekler ve seçenek yorumu kabuk ayarlarına bağlıdır. printf bir biçim dizgesine göre çalışır, yeni satırı yalnızca siz isterseniz ekler, sayıları biçimlendirir ve değerleri tutarlı biçimde yazar.
printf ile ondalık sayı hesaplanabilir mi?
printf ondalık sayıları biçimlendirebilir (%.2f), ama hesap yapmaz. Bash aritmetiği yalnızca tamsayılarla çalışır; ondalıklı hesap için dış bir araç gerekir. Sayıyı yalnızca yuvarlayıp göstermek için printf '%.1f' 2.345 yeterlidir.
printf ile bir sayının başına sıfır nasıl eklenir?
Genişlikten önce 0 bayrağı yazın: printf '%03d\n' 7 çıktısı 007 olur. Dosya adlarını sıralı numaralandırırken bu kalıbı printf -v ile birleştirip sonucu doğrudan bir değişkene alabilirsiniz.
printf neden biçimi birden fazla kez uyguluyor?
Kılavuza göre biçim, bütün argümanlar tüketilene kadar yeniden kullanılır. printf '%s\n' a b c üç satır yazar. Bu davranış istemediğiniz bir tekrar üretiyorsa, argümanları tek bir argümanda birleştirin ("$*") veya biçimdeki belirteç sayısını argüman sayısına eşitleyin.
printf çıktısı bir değişkene nasıl atanır?
printf -v hedef 'biçim' argümanlar yazın. Bu yöntem komut ikamesine göre alt kabuk açmaz ve çıktının sonundaki yeni satırları korur.
Bir değerde görünmeyen karakter olup olmadığını nasıl anlarım?
printf '%q\n' "$deger" ile yazdırın. Değer sekme, satır başı veya başka kontrol karakterleri içeriyorsa çıktı $'...' biçiminde gelir ve bu karakterler kaçış dizisi olarak görünür.
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ı · read ile girdi · String işlemleri · stdout ve stderr