Bash Kabuk Betikleme/Basit Komutlar
Basit bir komut, boşluk veya tab ile ayrılmış kelimelerden oluşur. İlk kelime komutun ismiyken geri kalan kelimeler komutun argümanları olarak tanımlanır. Önceki başlıkta bazı basit komut örnekleri görmüştük. Burada birkaç tane daha var:
cd ..
- Bu komut
cd
("change directory" = dizin değiştir; dosya sistemi içerisinde yolculuk yapmak için kullanılır)'yi bir dizin üste çıkmak için kullanmaktadır. ..
işareti "üst dizin" anlamına gelir. Örneğin/foo/bar/../baz.txt
ile belirtilen konum,/foo/baz.txt
konumunun eş anlamlısıdır.
- Bu komut
rm foo.txt bar.txt baz.txt
rm
komutunun yüklü geldiğini varsayarsak bu program mevcut dizindekifoo.txt
,bar.txt
vebaz.txt
isimli dosyaları siler.- Bash, harici olan
rm
programını yapılandırılabilir dizin listesinderm
isimli çalıştırılabilir bir dosya arayarak bulur.
/foo/bar/baz bip.txt
- Bu komut,
/foo/bar/baz
konumunda bulunan programı çalıştırır vebip.txt
'de bulunan argümanı kullanır. /foo/bar/baz
çalıştırılabilir olmalıdır.- Dikkat: Eğik çizgi ve dosya isimleri arasında BOŞLUK OLMAMASINA dikkat edin. Eğer
rm -r / foo
gibi boşluk nedeniyle kök dizini hedef alan bir komutu yönetici haklarıyla çalıştırırsanız bilgisayarınızın kök dizini silinebilir ve ayvayı yersiniz. - Eğer
/foo/bar/baz
ikili program yerine bir metin dosyasıysa ve ilk satırı#!
ile başlıyorsa o satırın hatırlatıcısı bu dosyayı çalıştırmak için gerekli olan yorumlayıcıyı (interpreter) belirler. Örneğin eğer/foo/bar/baz
konumunda bulunan dosyanın ilk satırı#!/bin/bash
ise üstteki komut/bin/bash /foo/bar/baz bip.txt
ile eş anlamlıdır.
- Bu komut,
/foo/bar/baz
ile yapılan örnek, herhangi bir program gibi çalışabilen Bash betiklerinin yapılabileceğini gösteren özel bir not içeriyor. Yalnızca #!/bin/bash
ifadesinin bir betiğin ilk satırına konulması ve okunup çalıştırılabilmesi için doğru dosya izinlerine sahip olması o betiğin bir program gibi çalışması için yeterli. Bir hatırlatma olarak bu kitaptaki tamamlanmış tüm kabuk betikleri #!/bin/bash
ile başlayacaktır.
Gezinme
değiştirİlk örnekte gördüğümüz üzere cd
komutu belirtilen argümanlar ile gezinmeye yarar. Unix ve GNU/Linux gibi Unix benzeri sistemlerde göreceli ve mutlak olmak üzere iki yol türü vardır. Göreceli yollar bulunduğunuz yola göre konumlanırken mutlak yollar nettir. Bu örnekte belirtilen mutlak yola gidiliyor:
cd 'örnek/dizin'
Göreceli yol gezinmesi için çeşitli kısayolları mümkün kılan belirli argümanlar vardır. 2 dizin üste çıkmak için şu argümanı kullanmalısınız:
cd ../../
Mevcut konumunuzdan önce bulunduğunuz konuma dönmek için şu argümanı kullanabilirsiniz:
cd -
İpucu:
|
Şu an üzerinde olduğunuz yolu öğrenmek için yaygın Unix araçlarından pwd
komutunu kullanabilirsiniz.
Alıntılama
değiştirYukarıda rm foo.txt bar.txt baz.txt
komutunun foo.txt
, bar.txt
, ve baz.txt
isimli üç dosyayı sildiğini gördük. Bu, Bash'in komutları boşluğa göre 4 farklı kelimeye ayırmasından ve o 3 kelimenin rm
programının argümanlarına dönüşmesinden kaynaklanıyor. Peki ya isminde boşluk olan bir dosyayı silmek istersek ne yapmalıyız?
Dikkat: Unix, GNU/Linux dağıtımları ve öbür Unix benzeri sistemlerde dosya isimleri boşluk, tab, yeni satır ve hatta kontrol karakterlerine sahip olabilir. |
Bash bu durumda işe yarayabilecek bazı alıntılama tekniklerine sahiptir. Bu teknikler arasında tek tırnak işaretleri '
ve çift tırnak işaretleri "
en yaygın olanlardır. Bu iki komut da bu dosya.txt
isimli bir dosyayı silecektir:
rm 'bu dosya.txt'
rm "bu dosya.txt"
Tırnak işaretleri içindeki boşluk karakterleri, kelime ayırma özelliklerini kaybeder. Normalde yukarıdaki gibi tüm kelime tırnak içine alınsa da yalnızca boşluğu this' 'file.txt
veya this" "file.txt
olarak tırnak içine almak da işe yarar.
Öbür sıklıkla kullanılan bir alıntılama mekanizması da ters eğik çizgi \
ifadesidir ancak yalnızca bir karakteri alıntıladığı (veya "atladığı") için tırnaklardan biraz farklı çalışır. Alttaki komut üstteki örneklerle aynı işlevi görür:
rm bu\ dosya.txt
Tüm bu durumlarda görülebildiği üzere alıntılama karakterleri programa dahil edilmemiştir. (Buna alıntı silimi denir.) Bu nedenle rm
komutu bu alıntıların çalıştırıldığına dair bilgi sahibi değildir. Örneğin rm foo.txt
veya rm 'foo.txt'
komutları rm
için aynıdır.
Dosya ismi uzantıları ve yaklaşık uzantılar
değiştirBash yaygın kullanılan argümanları programlara geçirmek için uzantı olarak bilinen bazı özel işaretleri destekler.
Bu işaretlerden birisi, *.txt
gibi bir desenin bu desene uyan tüm dosyalara tekabül etmesini sağlayan dosya ismi uzantısıdır. Örneğin mevcut dizin foo.txt
, bar.txt
, bu dosya.txt
, ve başka bir.şey
gibi dosyaları barındırıyorsa şu komut:
echo *.txt
bu komut ile aynı görevi görecektir:
echo 'bar.txt' 'foo.txt' 'bu dosya.txt'
Burada *
ifadesi "sıfır veya daha fazla karakter" anlamına gelir. Başka özel desen karakterleri (örneğin "tam olarak tek karakter" anlamına gelen soru işareti ?
) ve desen eşleştirme kuralları da vardır ancak *
ifadesinin bu kullanımı desenlerin en yaygın kullanımıdır.
Dosya isim uzantısı mevcut dizindeki dosyalarla sınırlı değildir. Örneğin eğer /usr/bin
dizini içindeki t*.sh
desenine uyan tüm dosyaları sıralamak istiyorsak şu komutu yazabiliriz:
echo /usr/bin/t*.sh
Bu komutu şu şekilde genişletebiliriz:
echo /usr/bin/test.sh /usr/bin/time.sh
Eğer hiçbir dosya belirtilen desene uymuyorsa herhangi bir ikame yaşanmaz. Örneğin şu komut yalnızca asfasefasef*avzxv
çıktısı verecek:
echo asfasefasef*avzxv
Peki ya eğer ismi *.txt
olan bir dosyayı belirtmek istiyorsak ne yapmalıyız? (Evet, dosya isimleri yıldız içerebilir!) O halde daha önce bahsettiğimiz alıntılama tekniklerinden tırnak işaretlerini kullanabiliriz:
cat '*.txt'
cat "*.txt"
İki komut da .txt
uzantısını içeren dosyalar yerine *.txt
isimli dosyanın içeriğini çıkartacaktır.
Başka benzer bir uzantı da yaklaşık uzantısıdır. Yaklaşık uzantısı çok daha fazla özelliğe sahiptir ancak en önemli özelliği yalnızca yaklaşık işaretine ~
veya eğik çizgi ile yaklaşık işaretine ~/
sahip bir kelimede yaklaşık işaretini dosyanın mevcut kullanıcının ev dizinine kadar olan konumuyla değiştirmesidir. Örneğin şu komut, mevcut kullanıcının ev dizininde *.txt
desenine uyan tüm dosyaları yazdıracaktır:
echo ~/*.txt
Ayraç uzantıları
değiştirAyraç uzantısı, dosya uzantısına benzer şekilde birden fazla benzer argümanı belirtmek için kullanılır. Aşağıdaki 4 komut birbirinin aynısıdır:
ls dosya1.txt dosya2.txt dosya3.txt dosya4.txt dosya5.txt
ls dosya{1,2,3,4,5}.txt
ls dosya{1..5..1}.txt
ls dosya{1..5}.txt
İlk komut her bir argümanı açıkça sıralar. Öbür üç komut belirtilen argümanları kısaca ifade etmek için ayraç uzantısı kullanır. İkinci komutta 1
'den 5
'e kadar olan ifadeler virgülle ayrılarak verilmiş. Üçüncü komutta ise numaralı bir sıra (1'den 5'e kadar, 1 arttırılarak) verilmiş. Dördüncü komut üçüncü komut ile aynı ancak ..1
ifadesi örtük.
Dosyaları ayrıca tersten de sıralayabiliriz.
ls dosya5.txt dosya4.txt dosya3.txt dosya2.txt dosya1.txt
ls dosya{5,4,3,2,1}.txt
ls dosya{5..1..-1}.txt
ls dosya{5..1}.txt
Son değer başlangıç değerinden düşük olduğu için örtük ifade -1
olmalıdır.
Bash'de bir komutun ilk kelimesi çalıştırılacak program olduğundan komutu şu şekil de yazabiliriz:
{ls,dosya{1..5}.txt}
Ayraç uzantıları aynı dosya ismi uzantıları gibi '{'
, "{"
, or \{
gibi alıntılama mekanikleriyle devre dışı bırakılabilir.
Çıktı yönlendirme
değiştirBash bir komutun standart çıktısının konsol yerine bir dosyaya gönderilmesine izin verir. Örneğin yaygın bir araç komutu olan cat
bir dosyanın içeriğini standart çıktı olarak yazdırır. Eğer bu standart çıktıyı bir dosyaya yönlendirirsek bu durumda bir dosyanın içeriğini başka bir dosyaya kopyalama işlemini gerçekleştirmiş oluruz.
Eğer hedef dosyanın içeriğinin komut çıktısı tarafından üstüne yazılmasını istiyorsak şu ifadeyi kullanmalıyız:
cat girdi.txt > çıktı.txt
Eğer hedef dosyanın içeriğinin korunup komut çıktısını dosyanın sonuna iliştirmek istiyorsak şu ifadeyi kullanacağız:
cat girdi.txt >> çıktı.txt
Ancak bir programın konsola yazdığı her şey standart çıktı formatında olmayabilir. Çoğu program hata çıktısı ve "giriş" veya "yan-kanal" mesajları için standart hata formatını kullanıyor. Eğer standart hata formatının da standart çıktıya dahil edilmesini istiyorsak şu ifadelerden birini kullanabiliriz:
cat girdi.txt &>> çıktı.txt
cat girdi.txt >> çıktı.txt 2>&1
Eğer hata çıktısının standart çıktıdan ayrı bir dosyaya yazılmasını istiyorsak şu ifadeyi kullanmalıyız:
cat girdi.txt >> çıktı.txt 2>> hata.txt
Aslında standart çıktıya dokunmayıp yalnızca hata çıktısını da yönlendirebiliriz:
cat girdi.txt 2>> hata.txt
Yukarıda gösterilen tüm örneklerde çıktıyı yönlendirme hedefindeki içeriğe iliştirmek yerine üstüne yazmak için >>
ifadesini >
ile değiştirebiliriz.
İlerleyen bölümlerde bu çıktı yönlendirmesiyle yapılabilecek daha gelişmiş örneklere bakacağız.
Girdi yönlendirme
değiştirBash bir programın çıktısının dosyaya yönlendirilmesine izin verdiği gibi program girdisini de dosyadan yönlendirebilir. Örneğin araç komutu olan cat
aşağıdaki örnekte belirtilen dosyadaki girdiyi çıktısına kopyalayıp girdi.txt
içeriğini konsola yazdırıyor:
cat < girdi.txt
Halihazırda gördüğümüz gibi cat
zaten girilen dosyanın içeriğini yazdırmak için kulllanılabilen bir komut olduğundan yönlendirme bu örnekte gerekli değildir ve aynı komut şu şekilde de yazılabilir:
cat girdi.txt
Bu bir istisnadan ziyade kuraldır. Konsoldan girdi alabilen çoğu sık kullanılan Unix aracı girdilerini belirtilen dosyadan alma özelliğine sahiptir. Doğrusu cat
de dahil olmak üzere birçok komut birden fazla dosyayı girdi olarak alarak yukarıdaki örnekten daha esnek kullanıma sahip olabilir. Aşağıdaki örnek sırasıyla girdi1.txt
ve girdi2.txt
'yi yazdırıyor:
cat girdi1.txt girdi2.txt
Bununla beraber girdi yönlendirmenin önemli olduğu kullanım alanları vardır ve onları ileriki örneklerde göreceğiz.
Bağlantı hatlarına giriş
değiştirBu bölümün kapsamının dışında olmasına karşın artık bağlantı hatlarına bakmak için gerekli bilgiye sahibiz. Bir bağlantı hattı (pipeline), bağlantı karakteri |
ile ayrılarak yazılmış komutlar serisidir. Serideki her bir komut aynı anda çalışır ve her bir komutun çıktısı bir sonrakinin girdisi olarak kullanılır.
Örneğin şu bağlantı hattını inceleyelim:
cat girdi.txt | grep foo | grep -v bar
cat
aracını daha önce görmüştük. cat girdi.txt
komutu basitçe girdi.txt
dosyasını standart çıktısı olarak yazdırıyor. grep
programı belirtilen şablona uygun olan ifadeleri filtreleyen (Unix konuşma dilinde "grepleyen") yaygın bir Unix aracıdır. Yukarıdaki örnekte de grep foo
komutu belirtilen girdide foo
ifadesini taşıyan satırları yazdıracaktır. grep -v bar
komutu ise şablonu tersine çeviren -v
argümanına sahiptir yani komut girdide bar
ifadesini taşımayan tüm satırları yazdıracaktır. Her komutun girdisi bir önceki komutun çıktısı olduğuna göre bağlantı hattı girdi.txt
dosyasındaki satırlardan sadece foo
ifadesini taşıyan ve bar
ifadesini taşımayanları yazdıracaktır.