Bash komut dosyasında bir komutun sonucunu ve dönüş kodunu aynı anda nasıl alabilirim?


0

Bash senaryoları ile oynuyorum. Bir komutun sonucunu bir değişkene ve dönüş kodunu bir başkasına atamak istiyorum.

Ör .:

line_count=$(cat "$filename" | wc -l) #If the file does not exist, an error code is returned
cmd_return_code=$? #I want to assign the previous error code to a variable

Kullanmaya çalıştım $? yukarıda gösterildiği gibi fakat önceki atamanın dönüş kodunu (0 olan) alır.

Bunu nasıl yapabilirim?

Teşekkürler


1
Gösterdiğiniz komutlar set cmd_return_code Komut ikamesinde boru hattının çıkış durumuna; yani, boru hattındaki son komutun çıkış durumu ( wc -l ). İstediğin buysa, farklı bir şey yaptığına dair hangi kanıtın var? Farklı bir şey istiyorsanız, nedir? (P.S.Yetkin Komutanınız bir UUOC (useless) cat ). line_count=$(wc -l < "$filename") daha verimli olurdu ve istediğiniz sonuçları size verebilir.)
G-Man

Yanıtlar:


3

Buradaki sorun boru hattında ki cat "$filename" | wc -l, dosya bulunmadığında cat bir hata ile çıkacak, ancak wc -l başarılı bir şekilde aldığı 0 metin satırını sayar. cat. Boru hattındaki son komutun çıkış durumu, boru hattının bir bütün olarak nihai durumu olarak değerlendirilir, bu nedenle tüm boru hattının başarılı olduğu kabul edilir. Bunun gibi:

$ cat nosuchfile | wc -l
cat: nosuchfile: No such file or directory
       0
$ echo "$?"
0

Normalde bash'ta, bir komut satırında bireysel komut durumlarını PIPESTATUS dizi, şöyle:

$ cat nosuchfile | wc -l
cat: nosuchfile: No such file or directory
       0
$ echo "${PIPESTATUS[@]}"
1 0

... ancak bu, komut genişletme komutunda bir boru hattıyla çalışmaz $( ), çünkü bu boru hattı bir alt kabukta çalışacak ve PIPESTATUS alt kabuktan yayılamaz; yalnızca son durum ana kabuğa geri döndürülür:

$ line_count=$(cat nosuchfile | wc -l)
cat: nosuchfile: No such file or directory
$ echo "${PIPESTATUS[@]}"
0

Peki bu konuda ne yapabilirsin? Şey, l0b0'ın dediği gibi, bir olasılık ... pipefail seçeneği. Komut dosyasının tamamı için bunu yapmak zorunda değilsiniz, yalnızca komut değiştirme içinde yaparak belirli bir alt kabuk için ayarlayabilirsiniz:

$ line_count=$(set -o pipefail; cat nosuchfile | wc -l)
cat: nosuchfile: No such file or directory
$ echo "$?"
1

Bu özel komut için, boru hattını da ortadan kaldırabilirsiniz (buna ne denir? İşe yaramaz kedi kullanımı veya UUOC ) ve sahip wc dosya adını parametre olarak ileterek doğrudan dosyadan okuyabilir:

$ line_count=$(wc -l nosuchfile)
wc: nosuchfile: open: No such file or directory
$ echo $?
1

... veya bir giriş yönlendirmesi kullanarak:

$ line_count=$(wc -l <nosuchfile)
-bash: nosuchfile: No such file or directory
$ echo $?
1

Bu iki seçenek arasında birkaç fark vardır: dosya adını iletirseniz wc (ve var), dosya adının yanı sıra satır sayısını da gösterecektir:

$ line_count=$(wc -l realfile.txt)
$ echo "$line_count"
       6 realfile.txt

... yönlendirme seçeneği ile olmaz. Ayrıca, ikinci seçenekle kabuk dosyayı açmaktan (ve açık dosya tanıtıcısını dosyaya teslim etmekten) sorumludur. wc komut), öyleyse bu başarısız olursa hata veren kabuktur (hata mesajının "-bash" ifadesinden geldiğini unutmayın wc ) ve wc asla kaçmaz.


2

çıkış kodu bir atama komut değiştirme komut değişikliğinin çıkış kodudur. Örneğin, çıkış koduna bakın. foo="$(false)".

Bir boru hattının çıkış kodunu, boru hattındaki ilk başarısız komutun çıkış kodunu yapmak için:

set -o pipefail
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.