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.txtile belirtilen konum,
/foo/baz.txtkonumunun eş anlamlısıdır.
- Bu komut
rm foo.txt bar.txt baz.txt
rmkomutunun yüklü geldiğini varsayarsak bu program mevcut dizindeki
foo.txt,
bar.txtve
baz.txtisimli dosyaları siler.
- Bash, harici olan
rmprogramını yapılandırılabilir dizin listesinde
rmisimli çalıştırılabilir bir dosya arayarak bulur.
-
/foo/bar/baz bip.txt
- Bu komut,
/foo/bar/bazkonumunda bulunan programı çalıştırır ve
bip.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 / foogibi 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/bazikili 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/bazkonumunda bulunan dosyanın ilk satırı
#!/bin/bashise üstteki komut
/bin/bash /foo/bar/baz bip.txtile 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ırlarma 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ştir]
Yukarı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 veta
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ştir]
Bash 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ştir]
Ayraç 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ştir]
Bash 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ştir]
Bash 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ştir]
Bu 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.