Düzey: Orta
Martin Streicher
(martin.streicher@linux-mag.com),
Şef Editör, Linux Magazine
06 Şubat 2007
UNIX® kendine ait bir dile sahiptir ve komut dağarcığı oldukça geniştir. Ancak, her şeyi bir defada öğrenmenize gerek yok.
Burada, daha fazla komut satırı bileşimlerini keşfetmeniz ve UNIX diline
hakimiyetinizi genişletmeniz amaçlanmaktadır.
Yabancı bir ülkeye seyahat ettiğinizde, o ülkede yaşayan insanlar
bilmediğiniz bir yerel dil konuşuyorlarsa, kendinizi "Bunun fiyatı ne?",
"Bu ne eti?" ve "Lavabo nerede?" gibi hayat kurtaracak sözlerle güvenceye
alabilirsiniz. Bu tür küçük hazır cümleleri ezberlemek, siparişini verdiğiniz
yılanlı sandviç için fazla ücret ödememenizi ve Tabiat Ana (ya da yılanlı
sandviç) çağırdığında nereye gideceğinizi bilmenizi sağlar.
UNIX® de kendine has bir dile sahiptir ve geçtiğimiz altı ay
içinde, bu UNIX Dilinde Konuşma serisi, komut satırı dili konusunda yoğun bir
kurs sağladı. Bu ay, yerlilerin arasına hemen karışmanızı sağlayacak bazı
yardımcı sözcük gruplarını öğreneceksiniz. Diş fırçanızı alın, rahat bir çift
ayakkabıyı ayağınıza geçirin ve aşılarınızı olun. Güneşe, kuma ve deniz
kabuklarına gidiyorsunuz. (Güneş ve kum için taşınabilir bilgisayarınızı
toplayın, plaja gidin, suyun kenarında oturup bu yazıyı okuyun. Ve güneş
kreminizi unutmayın.)
Yürüyüş turuna katılın
Önceki UNIX Dilinde Konuşma makalelerinin birçoğunda (bkz.
Kaynaklar), dosyaları ve hatta tüm UNIX dosya
sistemini taramak ve işlemek için paha biçilemez bir yardımcı program olan
find komutu anlatılmıştı. Örneğin, ben genellikle çok sayıda
dosyayı işlemek için find komutunu, grep ya da Perl
ile birlikte kullanırım. Geniş bir kod bütününde bir değişkenin ya da sabit
değerin nerede tanımlandığını bilmeniz mi gerekiyor? Aşağıdaki komutu
deneyin:
$ find /path/to/src
-type f | xargs grep -H -I -i -n
string
|
Komutun çıkışı, satır numarası ve eşleşen özel metnin yer aldığı,
string 'i (dize) içeren dosya adlarının bir listesi olur.
-H seçeneği, her bir eşleşmeyi, dosya adıyla ve -n ,
her bir eşleşmeyi satır numarasıyla başlatır. -i seçeneği,
büyük/küçük harfin dikkate alınmamasını sağlar. -I (büyük "I"),
ikili dosyaları atlar.
Daha önce xargs komutunu görmediyseniz,
belirlediğiniz komutu (burada, listelenen tüm seçeneklerle grep
komutu), standart giriş ile sağlanan her bir bağımsız değişken için bir kez
çalıştırır. /path/to/src dizininin a, b ve c dosyalarını içerdiğini
varsayarsak, find ile xargs komutunu birlikte
kullanmamız aşağıdakine eşdeğer olacaktır:
grep -H -I -i -n string a
grep -H -I -i -n string b
grep -H -I -i -n string c
|
Aslında, bir dosya koleksiyonunda arama yapmak o kadar yaygın bir
şeydir ki grep komutunun, bir dosya sistemi
hiyerarşini yinelemek için kendi seçeneği vardır. -d recurse ya da
eşanlamlıları olan -R ya da -r seçeneğini kullanın.
Örneğin:
$ grep -H -I -i -n -R string
/path/to/src
|
Bu komut, find/xargs ile aynı işlevi görür.
(Dosyalarla ilgili birçok UNIX yardımcı programının yineleme için seçenekleri
olduğunu göreceksiniz. ls -R , özyinelemeli olarak bir
hiyerarşinin içeriğini listeler. chmod , chgrp ve
chown , mod, grup ve sahiplik değişikliklerini tüm dosya
sistemi hiyerarşisine uygulamak için -R seçeneğini
kullanır. chmod -R komutunu kullanırken dikkatli olun. chmod
-R a-x komutunda olduğu gibi bir dizinin yürütme bitlerini
kaldırırsanız, yanlışlıkla dizini kullanılamaz hale getirebilirsiniz. Daha
seçici olmak için find . -type f | xargs chmod a-x komutunu
deneyin.)
Peki, ne zaman find /xargs , ne zaman
grep komutunu kullanmalısınız? find komutunu
kullanırken ne zaman seçici olmanız gerekir? find komutunun,
belirli gereksinimleri karşılayan dosyaları seçmenize olanak tanıyan birçok
koşulu vardır; "Ali'nin sahip olduğu ve geceyarısından sonra değiştirilen tüm
düzenli dosyalar" kavramsalı gibi. Aksi halde, grep -R yeterli
olacaktır.
Başka bir yardımcı program, find komutunu
kullanmaktan daha kullanışlı ve hızlı olabilir. Bir dosyayı adına göre
bulmaya çalışıyorsanız, find -name yerine locate
komutunu deneyin. locate komutu, sisteminizdeki her dosyayı
belirli aralıklarla (sistem yöneticinizin yaptığı ayara bağlı olarak günde bir
kez, vb.) sınıflandırır ve yollar ile dosya adlarının yer aldığı bir veritabanı
oluşturur. locate komutunu çalıştırdığınızda, özel veritabanını
tarayarak eşleşmeler oluşturmayı dener.
Örneğin, locate '*.1' sorgusunu çalıştırdığınızda,
adları .1 ile biten tüm dosyalar ve dizinler verilir. (Baştaki
yıldız işareti eşleşen her şey anlamına gelir.) Kolaylık olması
açısından, locate fish komutu ile locate '*fish*'
birbirinin aynıdır.
Para birimi
değişimi
Birçok UNIX yardımcı programı dosyaları değiştirir. Çoğu durumda,
değiştirilen içerik, standart çıkışa gönderilerek, sonuçları yeniden yönlendirme
işleçleriyle daha ayrıntılı bir şekilde işlemeniz (dikey çubuk kullanma, |) ya
da yakalamanız (> ya da >> işleçleri)
sağlanır.
Diğer yardımcı programlar, genellikle bir defada birçok dosyayı
işleyebilen, koruma amacıyla özgün dosyayı tutabilen ve değişen içerik için
yeni bir dosya oluşturan yardımcı programlardır. Örneğin, bir dosyayı işlemek
için komut satırından doğrudan Perl dizinini kullanabilirsiniz. Şu komut:
$ perl -i.bak -pe 's/\bdollar(s?)/buck\1/g' file.txt
|
"dollar" sözcüğünü "buck" ve "dollars" sözcüğünü "bucks"
sözcüğüyle değiştirir. perl -i komutu, mevcut file.txt
dosyasını değiştirir; perl -i.bak , özgün dosyanın bir kopyasını
oluşturur ve özgün dosyayı, yeni değiştirilmiş sürümden ayırt etmek için sonuna
bir .bak soneki ekler. Dolayısıyla, aşağıdaki gibi bir komut:
perl -i.bak -pe 's/\bdollar(s?)/buck\1/g' *
|
geçerli dizinde her dosya için bir yedek oluşturur. file1.txt,
file2.txt ve file3.txt dosyalarınız olsaydı, file1.txt.bak, file2.txt.bak ve
file3.txt.bak dosyalarınız olurdu. Hatalar olabilir, dolayısıyla bir yedek
oluşturmak akıllıca bir davranıştır.
Bir hata yaparsanız ve özgün dosyayı kurtarmanız gerekirse,
aşağıdakini yazmanız yeterlidir:
mv file1.txt.bak file1.txt
|
Ancak, yeniden adlandırılacak yüzlerce dosyanız varsa ne
olacak? Elbette, yüzlerce ayrı mv komutu yazmak istemezsiniz.
Bunun yerine, aşağıdakini yazabilirsiniz:
foreach file in (*.txt)
do
mv $file.bak $file
done
|
Bu komut, buradaki gibi basit durumlarda işe yarar. Ancak, bu tür
görevler çok yaygın olduğu için özel bir yardımcı program işi daha da hızlı
gerçekleştirmektedir. Şu komut:
$ rename 's/\.bak$//' *.bak
|
aynı görevi gerçekleştirir. s/\.bak$// düzenli
ifadesi, komut satırında listelenen her bir dosya adından (burada
* ya da every file) .bak sonekini kaldırır ve kısaltılmış
adı, hedef dosya adı olarak kullanır.
rename komutu, özellikle dosya adları düzensiz
olduğunda çok işe yarar. Örneğin, okula yeni başlayan bir öğrenin yazdığı
harflerin toplamına benzeyen bu dizinin içeriğini düşünelim.
$ ls RenT.txt bEErMoNey.txt gASmoNey.TXt
|
Yukarıda gösterilen foreach komut dosyası, dosya
adları çok düzensiz olduğu için bu sorunun üstesinden gelebilir. Yine de
rename , birkaç tuş vuruşuyla işlemi gerçekleştirebilir:
y/A-Z/a-z/ düzenli ifadesindeki y
işleci, çeviri için kullanılmıştır. Çeviri iki liste gerektirir: Özgün
karakterler listesi ve değiştirilecek karakterlerin listesi. İki listenin de
boyutu aynıysa, metindeki özgün listenin ilk karakterin her örneği, değişim
listesindeki ilk karakterle değiştirilir. Diğer bir deyişle, örnekte, büyük "A"
harfinin her örneği, küçük "a" harfiyle, "B" harfi "b" ile, vb. şekilde
değiştirilir. Metindeki küçük harfler değiştirilmeden bırakılır.
rename komutunun yapacaklarını önizlemek için komuta
-n seçeneğini ekleyin. Bu seçenek, gerçek değişiklikleri yapmadan
komutun eylemlerini gösterir:
$ rename -n 'y/A-Z/a-z/' *
RenT.txt renamed as rent.txt
bEErMoNey.txt renamed as beermoney.txt
gASmoNey.TXt renamed as gasmoney.txt
$ rename 'y/A-Z/a-z/' *
$ ls
beermoney.txt gasmoney.txt rent.txt
|
Dikkat edilmesi gereken bir nokta: UNIX sistemlerinde, dosya
adları büyük/küçük harfe duyarlıdır. Bir dizinde, Aa.Txt ve aA.txT dosyaları
bulunabilir. Yukarıda gösterildiği gibi büyük/küçük harfe duyarlı dosyaları,
küçük harfli dosya adlarına dönüştüren bir kural yazmak mümkündür; böylece,
önceden benzersiz olan dosya adları arasında çakışmalara neden olunabilir. Bu
durumda rename komutunun işlevi nedir? Görelim:
$ rename -n 'y/A-Z/a-z/' *
Aa.Txt renamed as aa.txt
aA.txT renamed as aa.txt
$ rename 'y/A-Z/a-z/' *
aA.txT not renamed: aa.txt already exists
$ ls
aA.txT aa.txt
|
Yeniden adlandırma işlemi ilerlerken var olan dosyaları iyice
değiştirmek istiyorsanız, -f işaretini ekleyin. Bu örnekte, sonuç
aa.txt adlı bir dosya olur. Peki, bu önceden hangi dosyaydı?
rename , alfabetik sırayla çalıştığından, sonraki aA.txT dosyası
artık aa.txt olmuştur. Neden -f seçeneğini kullanmalıyız? İki
dosya, adları dışında birbirinin aynıysa, rename -f komutu
kopyaları kaldırır.
Zaman, kaybetme zamanı
değil
UNIX kullanımının büyük bir kısmını dosya yönetimi oluşturur.
Sistemde sayısız yapılandırma dosyası vardır. Gerekenden çok daha fazla veri
dosyasına ve kişisel dosyaya sahip olabilirsiniz. Zaman zaman, yanlışlıkla
değerli bir dosyayı kaldırabilir veya dosyanın üzerine yazabilirsiniz. Kabuk ve
yönetim yardımcı programları, felaketi önlemenize yardımcı olabilir.
Kabuk komut istemine aşağıdaki komutları yazın. Bu komutlar
bash içinde çalışır, ancak zsh ve diğer
kabuklardakine benzer seçenekleri vardır.
$ alias mv=mv -i
$ alias rm=rm -i
$ set -o noclobber
|
İlk iki komut, komut satırında mv -i ile
mv ve rm -i ile rm komutunun yerine
geçer. Etkileşimli mod, sizi işleminizi onaylamaya zorlar.
Üçüncü komut, güvenliğin bir kısmını kabuğun kendi içinde sağlar.
noclobber etkin durumdayken, > yeniden
yönlendirme işlecini kullanarak yanlışlıkla bir dosyanın üzerine
yazamazsınız:
$ ls
secret.txt
$ cat > secret.txt
bash: secret.txt: cannot overwrite existing file
|
noclobber işlevini devre dışı bırakmak için
aşağıdakileri yazın:
Ayrıca, istediğiniz zaman >| (bir büyüktür işareti ve
ardından bir dikey çubuk) yeniden yönlendirme işlecini kullanarak bir üzerine
yazma işlemini de zorlayabilirsiniz.
$ cat secret.txt
I love green eggs and ham.
$ echo "No more secrets" >| secret.txt
$ cat secret.txt
No more secrets
|
Yerel halkın
sırları
Bir kenti gerçekten keşfetmek istiyorsanız, yerel meyhaneleri
ziyaret etmelisiniz. İşte size Zagat'ta yer alabilecek bir komut satırı
bileşimleri koleksiyonu.
mkdir -p , hızlı bir hiyerarşi oluşturma çalışması
yapar. -p seçeneği ile mkdir komutu, belirtilen
yolda bulunan her bir dizini ve alt dizini oluşturur:
$ mkdir -p make/many/directories/at/once
$ ls -R
./make:
many
./make/many:
directories
./make/many/directories:
at
./make/many/directories/at:
once
./make/many/directories/at/once:
|
Bir sonraki ödeme gününüzün ne zaman olduğunu bilmek isterseniz,
cal komutunu yazmanız yeterlidir. Hiçbir bağımsız değişken
olmadan, yalnızca cal komutu, içinde bulunduğunuz aya ilişkin takvimi
yazdırır. cal -3 komutu önceki, içinde bulunduğunuz ve sonraki ayı;
cal 06 2009 komutu da Haziran 2009 ayını gösterir. (Doğum günüm o
yıl Pazartesi gününe geliyor!)
$ cal
November 2006
Su Mo Tu We Th Fr Sa
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
$ cal 06 2009
June 2009
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
|
UNIX'te çok sayıda komut olduğu için tüm yardımcı programların tüm
seçeneklerini hatırlamak gerçekten imkansızdır. Aslına bakarsanız, bazen
yardımcı programın adını bile hatırlamayabilirsiniz.
Şaşkına döndüğünüzde man komutunu girin. Örneğin,
man komutunun nasıl kullanılacağını öğrenmek için man
man komutunu girin. man rm ve man mv
komutlarını kullanarak rm ve mv için hazırlanan
açıklamaları da görebilirsiniz. Ayrıca, aradığınız konuyu biliyorsanız, bu
konuyla ilgili man sayfalarının bir listesini bulmak için make -k
komutunu kullanabilirsiniz.
$ man -k cron
cron (8) - daemon to execute scheduled commands (Vixie Cron)
crontab (1) - maintain crontab files for individual users (V3)
crontab (5) - tables for driving cron
dh_installcron (1) - install cron scripts into etc/cron.*
|
Burada, man komutu, tek satırlık açıklamaları
cron sözcüğünü içeren yardımcı programların man sayfalarını buldu. Büyük
olasılıkla, bu man sayfalarında sistem işi zamanlama yardımcı programı olan
cron 'un nasıl kullanılacağı anlatılmaktadır.
Peki, bu küçük sayılar ne için kullanılıyor? Her bir sayı,
çevrimiçi UNIX kılavuzundaki bir bölümü belirtir. Bölüm 1, bir UNIX
kullanıcısının kabukta çalıştırabileceği tüm komutlar için ayrılmıştır. Bölüm
5'te dosya biçimleri anlatılır. Bölüm 8'de sistem yönetimi komutları
yer alır. Diğer bölümler, sistem çağrılarını (2), kitaplık çağrılarını (3) ve
diğer konuları içerir.
Gördüğünüz gibi, çoğu komut bir tür çıkış sağlar. Çoğu komut
satırı komutları, sonuçlar için standart çıkışı (stdout) kullanır.
Ancak bazıları, standart çıkışı ilerlemeyi ve standart hatayı (stderr) da hata
iletilerini göstermek için kullanır. Sık sık komut satırıyla çalışmaya müdahale
ettiği için oldukça yararlı olan bu tür bir çıkışı dikkate almak istemezseniz,
çıkışınızı UNIX bit sepetine (/dev/null) yeniden yönlendirebilirsiniz.
Bitler iade edilir, ancak kullanıma alınmaz.
Aşağıdaki basit örneği inceleyin:
$ ls
secret.txt
$ cat secret.txt
I am the Walrus.
$ cat secret.txt > /dev/null
$ cat socrates.txt > /dev/null
cat: socrates.txt: No such file or directory
$ cat socrates.txt >& /dev/null
$ echo Done.
Done.
|
cat komutunun standart çıkışını /dev/null dizinine
yönlendirirseniz, hiçbir şey görüntülenmez. Bunun nedeni, tüm bitlerin
sanal "kalıcı dikey dosyaya" atılmış olmasıdır. Ancak, bir hata
yaparsanız, standart çıkışta sağlanan hata iletileri görüntülenir. Tüm çıkışı
dikkate almamayı seçerseniz, stdout ve stderr
çıkışlarını bit sepetine göndermek için >& işlecini
kullanın.
/dev/null dizinini, var olan dosyaları boşaltmak ya da yeni, boş
dosyalar oluşturmak için sıfır uzunluklu bir dosya olarak da kullanabilirsiniz:
$ cat secret.txt
Anakin Skywalker is Darth Vader.
$ cp /dev/null secret.txt
$ cat secret.txt
$ echo "The moon is made of cheese!" > secret.txt
$ cat secret.txt
The moon is made of cheese!
$ cat /dev/null > secret.txt
$ cat secret.txt
$ cp /dev/null newsecret.txt
$ cat newsecret.txt
$ echo Done.
Done.
|
Bu arada, UNIX'i bir Macintosh makinede kullanırsanız, Terminal
penceresinde open komutunu deneyin. Örneğin, geçerli çalışma
dizininde poodle.jpg adlı bir dosya varsa, open poodle.jpg komutu
yerleşik Mac OS X resim görüntüleyicisi olan Preview uygulamasını başlatır ve
kanişinizin resmi görüntülenir. Mac OS X open komutu, komut satırı
ile Macintosh'un pencere ortamı arasında var olan harika bir bağlantıdır ve
genellikle, Finder uygulamasını yeniden sıralamaktan çok daha hızlıdır.
Yeniden gelmeniz gerekiyor!
Vay! Oldukça yoğun bir sınıf oldu, ama artık UNIX'te daha
da ilerilere gitmeye hazırsınız. Tabiat Ana çağırdığında, bit sepetini nerede
bulacağınızı bile biliyorsunuz.
Her zaman olduğu gibi anlatılacak daha çok şey var. Önümüzdeki
aylarda, UNIX Dilinde Konuşma serisinde iş denetimi, düzenli ifadeler
(kesinlikle garip bir dil, ancak hakim olması imkansız değil), Internet'ten
yüklediğiniz yeni yardımcı programların nasıl oluşturulacağı ve daha birçok
konu araştırılacaktır.
Güneş kreminizi unutmayın.
Kaynaklar Bilgi Edinme
- UNIX
Dilinde Konuşma: Bu dizinin diğer bölümlerini de inceleyin.
- Bu seriye ilişkin
RSS
haber kaynağı. (RSS ile
ilgili daha fazla bilgi öğrenin.)
- Martin Striecher'in yazdığı diğer makaleleri ve eğitici
yazıları okuyun:
- AIX ve UNIX kitaplığını konuya göre arayabilirsiniz:
- AIX ve UNIX: AIX ve UNIX
developerWorks bölgesi, AIX sistem yönetimiyle ilgili tüm durumları ve UNIX
becerilerinizi genişletmeye ilişkin çok çeşitli bilgileri sağlar.
- AIX ve UNIX'te yeni
olanlar: AIX ve UNIX ile ilgili daha fazla bilgi almak için New to AIX and UNIX
(AIX ve UNIX'te yeni olanlar) sayfasını ziyaret edin.
-
AIX 5L
Wiki: AIX ile ilgili teknik bilgilere ilişkin bir işbirliği ortamı.
- Safari kitapçısı: Özel teknik kaynakları bulmak için bu e-başvuru kitaplığını ziyaret edin.
-
developerWorks
teknik içerikli etkinlikler ve Web yayınları sayesinde güncel
bilgiler edinebilirsiniz.
- Podcasts: İlgili
ayarları yapın ve IBM teknik uzmanlarının bilgilerine ulaşın.
Ürün ve teknoloji edinme
- IBM
deneme yazılımı: developerWorks'deki yazılımı doğrudan yükleyerek bir sonraki
geliştirme projenizi oluşturun.
Tartışma
Yazar
hakkında
|
Martin Streicher, Linux Magazine adlı dergide Şef
Editör, bir Web geliştiricisi ve developerWorks topluluğuna düzenli katkıda
bulunan bir katılımcıdır. Streicher, Purdue University'den bilgisayar bilimi
konusunda bir Master derecesi almıştır ve 1986 yılından bu yana UNIX benzeri
sistemlerde programlama yapmaktadır. Martin Streicher'a
martin.streicher@linux-mag.com
adresinden erişebilirsiniz.
|
|
Web sayfalarında 'cal' programından tarihleri düzenli bir biçimde göstermek için oldukça yararlanılıyor.
Özellikle scriptin yolunu browserdan açık bir şekilde düzenlediğimizi düşünürsek:
http://www.adres.com/cgi-bin/refcal?2008
buradaki refcal scripti 2008 değerini alıyor ve calc programına gönderiyor. Eğer scriptin yazarı istenilen önlemi almaz ise yani 2008 yılından gelen veriyi şu şekilde kontrol etmez ise:
if ($year && ($year =~ /^\\s*\\d+\\s*$/)) {
#burada $year değişkeni ile istenilen yapılabilir
}else {
print "Hata oluştu $year değişkeni istenilen gibi değil.";
}
Şu şekildeki bir adres satırı istenilmeyen sonuçlar doğuracaktır.
http://www.adres.com/cgi-bin/refcal?2007;cat+/etc/passwd
Bu sadece 'cal' programına has bir durum değil.
PHP'deki, system(),shell_exec(),passthru() ve exec() fonksiyonları,Perl'deki ve Python'daki bu programların denkleri bilgisayar korsanları için vazgeçilmez açık kapılarıdır.Çünkü bu fonksiyonlar ile serverdaki programlara erişim sağlayabilirler.
Kısaca, server tarafında program çalıştıran fonksiyonlar her zaman bu açığı verirler; yapmamız gereken gelen verinin istediğimiz şekilde olup olmadığını kontrol etmekdir.