Bash'ın koşullu ifadelerinde -a ve -e arasındaki fark nedir?


12

Gönderen man bash:

CONDITIONAL EXPRESSIONS
[...]
       -a file
              True if file exists.
[...]
       -e file
              True if file exists.
  1. Öyleyse [ -a $FILE ]ve [ -e $FILE ]eğer varsa arasındaki fark nedir?
  2. Gerçek bir fark yoksa, neden aynı amaç için iki bayrak var?

Akıl yürütmelerini toplumla paylaşmadıkları sürece sadece geliştiriciler # 2'yi bilirdi.
Belmin Fernandez

Yanıtlar:


13

İçinde bash, iki argüman bağlamında testkomut -a fileve -e fileaynıdır. Ama bir farkları var, çünkü -aaynı zamanda bir ikili operatör.

-eunary POSIX tarafından tanımlanır, ancak -aunary tanımlanmaz . POSIX yalnızca -aikili dosyayı tanımlar (bkz. Test POSIX).

POSIX üç bağımsız değişken testdavranışı tanımlar :

3 argüman:

  • $ 2 bir ikili birincilse, $ 1 ve $ 3 ikili testini gerçekleştirin.

  • 1 $ '!' İse, 2 $ ve 3 $ 'lık iki argümanlı testi reddedin.

  • 1 $ '(' ve 3 $ ')' ise, 2 $ 'lık tekli testi gerçekleştirin. XSI seçeneğini desteklemeyen sistemlerde, eğer $ 1 '(' ve $ 3 '' 'ise sonuçlar belirtilmez.

  • Aksi takdirde, belirtilmemiş sonuçlar üretir.

Böylece -agarip bir sonuca da yol açar:

$ [ ! -a . ] && echo true
true

-aüç argüman bağlamında ikili operatör olarak kabul edilir. Bash SSS sorusu E1'e bakın . POSIX ayrıca -aKornShell'den alındığını ancak ikili ve tekli -earasında kafa karıştırıcı olduğu için değiştirildi .-a-a

C kabuğunun sağladığı işleve benzer işlevselliğe sahip olan -e birincil, bir kabuk komut dosyasının dosyayı açmaya çalışmadan bir dosyanın var olup olmadığını bulmasının tek yolunu sağladığı için eklenmiştir. Uygulamaların ek dosya türleri eklemesine izin verildiğinden, taşınabilir bir komut dosyası şunları kullanamaz:

test -b foo -o -c foo -o -d foo -o -f foo -o -p foo

foo'nun mevcut bir dosya olup olmadığını öğrenmek için. Geçmiş BSD sistemlerinde, bir dosyanın varlığı şu şekilde belirlenebilir:

test -f foo -o -d foo

ancak mevcut bir dosyanın normal bir dosya olduğunu belirlemenin kolay bir yolu yoktu. Erken bir öneri KornShell -bir birincil (aynı anlama gelen) kullandı, ancak -e ikil operatörü ile -a birincil olanı kafa karıştırıcı insanların yüksek olasılığı hakkında endişeler olduğu için bu -e olarak değiştirildi.

-aİkili de eskimiş olarak işaretlenir, çünkü 4'den fazla argümana sahip belirsiz bir ifadeye yol açar. Bu> 4 bağımsız değişken ifadesi ile POSIX, sonucun belirtilmediğini tanımlar.


Bilmek güzel! Şimdi biraz daha açık :)!
Polym

9

0,1. Peki, [-a $ FILE] ve [-e $ FILE] arasındaki fark nedir?

Hiç fark yok.

Doğrultusunda 505-507içinde test.cbash versiyonunun 4.2.45(1)-release:

case 'a':           /* file exists in the file system? */
case 'e':
  return (sh_stat (arg, &stat_buf) == 0);

Bu, her iki bayrak arasında gerçek bir fark olmadığını gösterir.

0,2. Gerçek bir fark yoksa, neden aynı amaç için iki bayrak var?

Gnouc'un cevabına bakınız .


3
Öte yandan, aynı zamanda bash'da bir boole operatörü (ve) -aolduğu göz önüne alındığında , tamamen gereksiz olan bu ek anlamı eklemeye eğilimli görünüyor; Daha başka bir uygulama ile uyumluluk ve / veya sahip olmayan önceki sürümlerle uyumluluk ile ilgili olduğunu tahmin ediyorum . -e
celtschk

@celtschk - o bugprone değil, ama kabuk ayrıştırıcı olabilir. POSIX için -ave -oboole değerlerini belirtir [ test ]. Ancak bazı mermiler (bir gibi bash) bir argümanı operatörden ayırmak için emilir ve [ test ]sonuçlar güvenilmezdi. O zamandan beri POSIX, herhangi bir uyumlu kabuğun [ test ]parantez içinde en az 4 argüman ele almasını gerektirdi .
mikeserv

5

Bulduğum en iyi yanıt, bir StackOverflow sorusundan:

-akullanımdan kaldırılmıştır, bu nedenle /usr/bin/testartık man sayfasında listelenmemiştir , ancak yine de bash içindedir. Kullanın -e. İçin tek '[', aynı şekilde davranır yerleşik darbe testaynı şekilde davranır Bash, /usr/bin/[ve /usr/bin/test (bir diğer sembolik olan). Etkisinin -akonumuna bağlı olduğuna dikkat edin: Başlangıçta varsa, demektir file exists. İki ifadenin ortasındaysa mantıklı demektir and.

[ ! -a /path ] && echo existsbash el kitabının -aorada ikili bir operatör olarak kabul edildiğine işaret ettiği için çalışmaz ve bu nedenle yukarıdakiler negate -a ..bir if '!' and '/path' is true(boş olmayan) olarak ayrıştırılmaz . Böylece, betiğiniz her zaman çıktıdır "-a"(aslında dosyaları test eder) ve "! -a"aslında andburada bir ikili olan .

Çünkü [[, artık -abir ikili olarak kullanılmaz (orada kullanılır), bu nedenle benzersiz amacı, orada bir dosyayı (kullanımdan kaldırılsa da) kontrol etmektir. Yani, olumsuzlama aslında beklediğinizi yapar.and&&

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.