리눅스 명령행 인자: 명령어 옵션과 따옴표, 옵션 끝 표시, $1, $# 받기
Linux komut satırı argümanları (command-line argument), komut adının ardından boşluklarla ayrılarak yazılan ve programa aktarılan değerlerdir. Bir AlmaLinux 9 sunucusunda, aldığı argümanları olduğu gibi yazdıran bir test betiğine seçenekler, tırnaklar, joker karakterler ve -- verdik: argümanları ayıran kabuktu, seçenekleri okuyan ise her komutun kendisiydi.
Aşağıdaki çıktı, bir AlmaLinux 9.8 sunucusunun root hesabında bash 5.1 ile çalıştırılan sonucun aynısıdır. Test betikleri ve örnek dosyalar ayrı bir çalışma klasöründe oluşturuldu; /home/user/www yolu örnek bir değerdir.
1️⃣ Linux komut satırı argümanları nedir?
Komut satırına [komut arg1 arg2] gibi bir şey yazdığınızda kabuk sözcükleri boşluklardan ayırır. İlk sözcük çalıştırılacak program olur, kalan sözcükler ise sırayla o programa argüman olarak aktarılır.
Aktarılan argümanları görmek için çalışma klasöründe args.sh oluşturduk. $0 çalıştırıldığı adı, $# argüman sayısını, $1 ve sonrası ise argümanları sırayla tutar. Köşeli ayraçlar her argümanın nerede başlayıp bittiğini göstermek için eklendi.
#!/bin/bash
echo "\$0 = $0"
echo "\$# = $#"
i=1
for a in "$@"; do
echo "\$$i = [$a]"
i=$((i+1))
doneBetiğe çalıştırma izni verdikten sonra onu üç sözcükle çalıştırdık: a, b ve c.
./args.sh a b c$0 = ./args.sh
$# = 3
$1 = [a]
$2 = [b]
$3 = [c]Üç sözcük $1, $2 ve $3'e girdi ve $# 3 oldu. Betiği adını bash'in ardına yazarak çalıştırırsanız $0, yazdığınız ad olan args.sh'yi aynen tutar.
bash args.sh a b c$0 = args.sh
$# = 3
$1 = [a]
$2 = [b]
$3 = [c]Yalnızca $0, args.sh olarak değişti; üç argüman ve sayıları öncekiyle aynıydı.
2️⃣ Komut satırı argümanları ve komut seçenekleri
Linux komutları genellikle [komut -seçenek argüman] sırasıyla yazılır. Seçenekler komutun nasıl çalışacağını değiştirir, argümanlar ise komutun üzerinde çalışacağı dosyaları, yolları ya da değerleri belirler.
ls -l /home/user/wwwKabuk açısından -l de yalnızca bir argümandır. Aynı sözcükleri args.sh'ye verdiğimizde -l $1'e, yol ise $2'ye girdi.
./args.sh -l /home/user/www$0 = ./args.sh
$# = 2
$1 = [-l]
$2 = [/home/user/www]-l'yi seçenek olarak okuyan ls'dir. Bu yüzden aynı harf her komutta farklı anlama gelir: head'deki -n yazdırılacak satır sayısını belirler, ls'deki -n ise sahipleri ad yerine numara olarak gösterir.
Bazı seçenekler hemen ardından gelen sözcüğü kendi değeri olarak alır. find komutunda -type f'yi, -name ise "*.txt"yi kendi değeri olarak kullanır; seçeneğe bu şekilde bağlı değere seçenek argümanı denir.
find . -type f -name "*.txt"Bu komuttaki baştaki . hiçbir seçeneğe bağlı olmayan bir argümandır ve aramanın başlayacağı klasörü belirler.
3️⃣ Linux komut seçeneği biçimleri
Tek tireyle başlayan kısa seçenekler tek harftir ve birkaçı bitişik yazılabilir. Önce çalışma klasöründeki site klasörünü [ls -l -a] ile listeledik.
ls -l -a sitetotal 8
drwxr-xr-x 3 root root 52 Oct 28 16:00 .
drwxr-xr-x 3 root root 137 Oct 29 01:20 ..
-rw-r--r-- 1 root root 17 Oct 28 16:00 .htaccess
drwxr-xr-x 2 root root 23 Oct 28 16:00 css
-rw-r--r-- 1 root root 14 Oct 28 16:00 index.htmlArdından bunu, iki harfi bitişik yazan [ls -la] çıktısıyla diff kullanarak karşılaştırdık.
diff <(ls -l -a site) <(ls -la site) && echo samesameİki çıktı arasında tek bir karakter bile fark yoktu. İki tireyle başlayan uzun seçenekler sözcük olarak yazılır; ls'deki --all, -a ile aynı seçenek olduğundan [ls -l --all site] da aynı sonucu verdi.
Uzun seçenekler, yalnızca başı yazılsa bile tek bir seçeneğe karşılık geliyorsa kabul edilir. --al, --all ve --almost-all olmak üzere iki seçeneğe uyduğu için ls liste yazdırmadı ve 2 çıkış koduyla bitti.
ls --al sitels: option '--al' is ambiguous; possibilities: '--all' '--almost-all'
Try 'ls --help' for more information.Değer alan seçenekler birkaç biçimde yazılabilir. head ile a.txt'nin ilk iki satırını yazdırırken kısa seçenek değeri bitişik alarak [-n2] şeklinde yazılabilir.
head -n2 a.txtalpha
betaUzun seçenek değeri eşittir işaretiyle bağlar: [--lines=2].
head --lines=2 a.txtalpha
betaBoşlukla ayrılmış [-n 2] ve [--lines 2] dahil dört biçimin hepsi alpha ve beta olmak üzere iki satırı yazdırdı.
ls, head ve cat seçeneklerini C kütüphanesinin getopt_long işleviyle okur. Üç program dosyasına strings ile bakınca hepsinde bu işlev adının bulunduğu görüldü.
Aynı kuralları kabukta denetlemek için util-linux'taki getopt komutu kullanılır. -o'nun ardına kısa seçenekler, -l'nin ardına uzun seçenekler yazılır; bir harfin ardındaki iki nokta, o seçeneğin değer aldığı anlamına gelir.
getopt -o lan: -l all,lines: -- -la -n 2 --all a.txt -l -a -n '2' --all -- 'a.txt'Bitişik yazılan -la, -l ve -a olarak ayrıldı; -n 2 ise -n ve 2 değeri olarak birleştirildi. Seçenek olmayan a.txt en sona, -- işaretinin ardına taşındı.
4️⃣ Tırnak içindeki argümanlar ve joker karakterler
Boşluk içeren bir dosya adı, tek bir argüman olarak aktarılması için tırnak içine alınmalıdır.
./args.sh "my file.txt" report.txt$0 = ./args.sh
$# = 2
$1 = [my file.txt]
$2 = [report.txt]Tırnaksız yazınca my ile file.txt ayrı ayrı bölündü ve $# 3 oldu. Bunu ls veya cat'e böyle verirseniz my ve file.txt adlı iki dosyayı arar.
./args.sh my file.txt report.txt$0 = ./args.sh
$# = 3
$1 = [my]
$2 = [file.txt]
$3 = [report.txt]Joker karakterleri, program almadan önce kabuk dosya adlarına çevirir. Çalışma klasöründe *.txt verdiğimizde .txt ile biten dört dosya ad sırasıyla geldi.
./args.sh *.txt$0 = ./args.sh
$# = 4
$1 = [a.txt]
$2 = [b.txt]
$3 = [my file.txt]
$4 = [report.txt]Tırnak içindeki "*.txt" kabuk tarafından değiştirilmedi ve harfi harfine tek bir argüman oldu. find'ın -name seçeneği gibi deseni programın kendisinin karşılaştırdığı seçeneklerde, değer bu şekilde tırnak içinde verilir.
./args.sh "*.txt"$0 = ./args.sh
$# = 1
$1 = [*.txt]Boş tırnaklar da tek bir boş argüman olarak aktarılır. [./args.sh '' b] çalıştırıldığında $# 2 oldu ve $1 boştu.
5️⃣ Komut seçeneklerinin sonu (--)
Adı -n olan bir dosya gibi tireyle başlayan argümanları komut seçenek olarak okur. Yalnızca o dosyanın bulunduğu dash klasöründe [ls -n] çalıştırdığımızda ls, -n'yi dosya adı olarak değil sayısal çıktı seçeneği olarak aldı ve klasörü listeledi.
ls -ntotal 4
-rw-r--r-- 1 0 0 10 Oct 28 16:00 -n-- işaretinin ardına yazılan argümanlar tireyle başlasa bile seçenek olarak okunmaz. [ls -- -n] yalnızca -n adlı dosyayı yazdırdı.
ls -- -n-nTek bir komutun içinde de aynı karakterler -- öncesinde ve sonrasında farklı okunur. cat'e -n'yi iki kez verdiğimizde öndeki -n satır numarası seçeneği, -- sonrasındaki -n ise dosya adı olarak okundu ve dosya içeriği satır numaralarıyla çıktı.
cat -n -- -n 1 dash fileBaşına yol ekleyip ./-n yazmak da bir yöntemdir; bu durumda argüman tireyle başlamadığı için aynı -n dosyası olarak okunur.
-- işaretini seçeneklerin sonu olarak okumak da komut tarafının bir kuralıdır. Seçenek okumayan args.sh'ye verdiğimizde -- da olduğu gibi $1'e girdi.
./args.sh -- -a$0 = ./args.sh
$# = 2
$1 = [--]
$2 = [-a]POSIX yardımcı program kuralları, seçenek argümanı olmayan ilk -- işaretinin seçeneklerin sonu olarak kabul edilmesini öngörür. Bu nedenle bu kurallara uyan komutlarda - ile başlayan dosya adları -- işaretinin ardına yazılır.
6️⃣ Kabuk betiğinde komut satırı argümanlarını almak
Kabuk betiği aldığı argümanları konumsal parametreler ve özel parametrelerle okur. Bir C programının main(int argc, char *argv[]) işlevi de aynı argümanları aldığından, ikisi yan yana konunca aşağıdaki gibi görünür.
| Parametre | İçerdiği değer | C dilinde main işlevi |
|---|---|---|
| $0 | Çalıştırılan betiğin adı | argv[0] |
| $1 ~ $9 | Birinciden dokuzuncuya kadar argümanlar | argv[1] ~ argv[9] |
| ${10} | Onuncu argümandan itibaren süslü parantez içinde | argv[10] |
| $# | Argüman sayısı, $0 sayılmaz | argc - 1 |
| "$@" | Tüm argümanlar, her biri ayrı | argv[1]'den sonuna kadar |
| "$*" | Tüm argümanlar boşlukla birleştirilmiş tek bir değer | — |
Bir Python programı aynı argümanları sys.argv listesi olarak alır. [python3 -c] ile üç argüman verdiğimizde tırnak içindeki my file.txt listenin tek bir öğesine girdi, ilk öğede ise -c vardı.
python3 -c 'import sys; print(sys.argv)' a "my file.txt" -l['-c', 'a', 'my file.txt', '-l']"$@" ve "$*" çift tırnak içine alındığında farklı sonuç verir. Bu farkı görmek için iki biçimi art arda yazdıran star.sh'yi oluşturduk.
#!/bin/bash
echo 'with "$@"'
printf ' [%s]\n' "$@"
echo 'with "$*"'
printf ' [%s]\n' "$*"star.sh'yi üç argümanla çalıştırdık: a, "b c" ve d.
./star.sh a "b c" dwith "$@"
[a]
[b c]
[d]
with "$*"
[a b c d]"$@" üç argümanı ayrı ayrı aktardı, "$*" ise onları boşlukla birleştirip tek bir argüman olarak aktardı.
Bu yüzden alınan argümanları başka bir komuta olduğu gibi aktarırken "$@" kullanılır.
shift, $1'i atar ve kalan argümanları birer konum öne kaydırır. Önce bir seçeneği okuyup gerisini dosya listesi olarak işleyen betiklerde kullanılır.
shift öncesinde ve sonrasında $1 ile $# değerini yazdıran shift.sh'yi oluşturduk.
#!/bin/bash
echo "before shift: \$1 = $1, \$# = $#"
shift
echo "after shift: \$1 = $1, \$# = $#"shift.sh'yi üç argümanla çalıştırdık: -v, a.txt ve b.txt.
./shift.sh -v a.txt b.txtbefore shift: $1 = -v, $# = 3
after shift: $1 = a.txt, $# = 2Onuncu argümandan itibaren sayı ${10} gibi süslü parantez içine alınır. $10 ile ${10} değerini yan yana yazdıran ten.sh'yi oluşturduk.
#!/bin/bash
echo "\$10 = $10"
echo "\${10} = ${10}"ten.sh'ye a'dan k'ye kadar 11 argüman verdik.
./ten.sh a b c d e f g h i j k$10 = a0
${10} = j$10, $1'in ardına 0 eklenmiş a0 olarak, ${10} ise onuncu argüman j olarak çıktı.
🔲 Komut satırı argümanı simülatörü
Aşağıdaki simülatörde args.sh'ye tırnak, joker karakter ve -- vererek deneyebilir, ls ile getopt'un seçenekleri nasıl okuduğunu, star.sh ile shift.sh'nin argümanları nasıl aldığını da komutları kendiniz yazarak görebilirsiniz.
🔢 SSS & önerilen içerikler
Joker karakterler
[Kabuk özel karakterleri] Linux joker karakterleri (meta karakterler)
* ve ? gibi joker eşleştirme karakterleri ve karakter sınıflarıyla dosya adlarını seçmenin yolunu örneklerle özetleyen yazı.
Çoklu komut
[Linux] Komutları zincirlemenin 5 yolu (noktalı virgül, boru, ve işareti..)
Noktalı virgül, boru, &&, || ve & ile tek satırda birden fazla komutu art arda çalıştırmanın beş yolunu özetleyen yazı.
Metin yazdırma
echo komutu: From genişletme ve tırnaklama
echo ile metinleri ve değişken değerlerini yazdırmanın yolunu ve seçeneklerini özetleyen yazı.
ℹ️ Satış ortaklığı bildirimi
Bu sitenin içeriklerinde satış ortaklığı bağlantıları bulunur. Bir ziyaretçi bu bağlantılar üzerinden ürün veya hizmet satın alırsa bu site satıcıdan komisyon alır. Bu süreçte alıcının ödediği tutar (kampanya indirimlerinde tutar düşer↓) artmaz. Yayımlanan fiyat, indirim ve stok bilgileri yazının yazıldığı zamana aittir ve gerçek durumdan farklı olabilir; bu yüzden satın almadan önce son bilgiyi satıcıdan kontrol etmenizi rica ederiz. Ürünler kendi ölçütlerimize göre seçilir ve değerlendirilir; komisyon alınıp alınmaması tanıtım sırasını veya değerlendirme içeriğini etkilemez.