Apakah ada perbedaan antara '&&' dan ';' simbol di terminal BASH standar?

57

Mereka berdua mengisyaratkan BASH untuk memulai dengan perintah lain mengikuti simbol tetapi apakah ada perbedaan yang berbeda?

Michael Terry
sumber

Jawaban:

76

Dengan garis ini:

command1 && command2

command2 akan dieksekusi jika (dan hanya jika) command1 mengembalikan status keluar nol, sedangkan di baris ini:

command1 ; command2

baik command1 dan command2 akan dieksekusi tanpa peduli. Tanda titik koma memungkinkan Anda mengetik banyak perintah pada satu baris.


sumber
1
Menarik! Saya pikir itu mungkin cara yang lebih nyaman. Terima kasih!
42

Anda dapat mencoba perbedaannya sendiri:

  1. ls /invalid/path && echo "hello!"
    karena / tidak valid / path tidak ada, ia tidak dapat menampilkan daftar direktori. Ini akan gagal dengan pesan kesalahan: "ls: / invalid / path: Tidak ada file atau direktori".
    Bagian kedua dari perintah (echo "hello!") Bahkan tidak pernah dieksekusi karena bagian pertama gagal.

  2. ls /invalid/path ; echo "hello!"
    Pesan kesalahan yang sama muncul seperti sebelumnya, tetapi kali ini, bagian kedua dieksekusi !
    ls: / invalid / path: Tidak ada file atau direktori tersebut
    halo!

Mengapa ini berguna?
Misalkan Anda ingin mengekstrak file bernama archive.tar.gz
Anda bisa menggunakan perintah tar zxvf archive.tar.gz && rm archive.tar.gz.
Jika karena alasan apa pun ekstraksi arsip gagal, bagian kedua tidak dijalankan! Anda bisa coba lagi.

Jika Anda menggunakan; dalam situasi yang sama, arsip dihapus dan Anda tidak dapat mencoba lagi.

Kenny Rasschaert
sumber
8

&&adalah AND, yang berarti bahwa perintah kedua hanya akan dieksekusi jika yang pertama dikembalikan dengan benar (tidak ada kesalahan).

Ward Muylaert
sumber
1
&& adalah "lalu" (bukan "dan") ... lihat jawaban saya
Peter.O
2
@ Fred Saya akan mengatakan ini adalah "dan" dengan evaluasi hubung singkat - jika bagian pertama adalah non-benar ia tahu bahwa hasil total pasti salah, sehingga melewatkan bagian kedua. Tetapi setuju bahwa menganggapnya sebagai "lalu" jarang membuat banyak perbedaan dalam konteks ini.
jg-faustus
2
@ Fred Meskipun secara konseptual mungkin lebih mudah untuk memahaminya seperti itu, saya tidak setuju dengan pernyataan Anda. Idenya secara sederhana adalah bahwa dengan setiap AND eksekusi parameter ke-2 menjadi tidak relevan jika yang pertama sama falsedan dengan demikian kode yang mendasarinya dioptimalkan untuk menunda evaluasi parameter ke-2 sampai ia tahu apa yang pertama.
Ward Muylaert
2
@ Fred Saya tidak yakin poin apa yang coba dibuat oleh contoh itu. &&hanyalah operator biner, sebuah fungsi. Satu-satunya hal yang "istimewa" adalah notasi infiks (yang merupakan standar untuk sebagian besar dari operator semacam ini) dan menunda pelaksanaan operan kedua. Eksekusi yang tertunda itu memang memberikannya kemampuan untuk digunakan sebagai sesuatu yang dapat secara konseptual dipandang sebagai ifpernyataan dalam konteks ini , tetapi itu tidak menghilangkan fakta bahwa penggunaan yang semula dimaksudkannya adalah dalam kondisi ifpernyataan aktual . Penggunaan di sini benar-benar lebih dari "hack".
Ward Muylaert
3
@ Fred Tentu saja itu bukan operator ternary, itu hanya merupakan suksesi dari dua operasi a && b || c = (a && b) || c. Urutan evaluasi sederhana. Benar-benar tidak ada misteri di sana. Jika Anda ingin menuliskannya seperti fungsi khas Anda, itu akan terlihat seperti or(and(a, b), c). Logika ini sama dalam ifkondisi dan juga ketika memasukkannya langsung ke baris perintah karena &&dan ||adalah operator , mereka mengambil dua operan dan mereka mengembalikan yang lain.
Ward Muylaert
8

Pembaruan : Saya telah menambahkan sebagai skrip untuk menyoroti beberapa perangkap yang mungkin:

Karena tidak ada orang lain yang menyebutkan "||", saya akan melakukannya

Pembaruan2 : beberapa pengulangan kata-kata penting di sini
&& adalah seperti pernyataan "lalu" dari pernyataan "jika" yang merespons "benar"

|| adalah TIDAK seperti "lain" dari "jika" pernyataan ..
|| seperti "lalu" dari pernyataan "jika" yang merespons "salah"

Lebih spesifik, && menguji $? mengembalikan nilai pernyataan yang terakhir dieksekusi sebelumnya dan memberikan kontrol ke pernyataan atau sub-shell segera setelah && ... hanya melewati kontrol jika $? adalah benar.

|| mirip, dan sering terlihat mengikuti pernyataan &&, tetapi tes untuk palsu nilai kembali ($?) dari sebelumnya yang paling baru-baru ini dieksekusi pernyataan ... NB! , Nota Bene! Catat dengan baik! .... jika pernyataan predecing adalah pernyataan && yang mengoreksi kembali kesalahan ketika Anda mengharapkannya benar, maka || akan merespons yang salah, sehingga menggabungkan keduanya pada baris yang sama mungkin berisiko

Poin utama yang saya coba buat adalah sehubungan dengan kesalahan yang saya buat. yaitu:
## [[kondisi]] ​​&& A || B
adalah tidak tidak berperilaku seperti C / C ++ gaya ternary. yaitu:
// (kondisi)? A: B
Lihat skrip di bawah ini untuk contoh hasil "tak terduga" dari "A"

Tes dasar dan && dan || pernyataan semua harus di baris yang sama ...


Jalankan skrip ini untuk mengetahui kesalahan apa yang terjadi saat menggunakan && dan ||
Pernyataan yang baru saja dieksekusi mungkin bukan yang Anda harapkan ..

[[kondisi]] ​​&& gema Halo || echo Goodbye .... biasanya aman,
karena gema yang terbentuk dengan baik akan mengembalikan true.
tetapi bagaimana dengan mengakses file yang tidak keluar?

#!/bin/bash
#
# "as expected" return codes" means: expected to behave like a normal AND / OR  contition test
#
if [[ "$1" != "" ]] ; then exit $1; fi # recursive call to return an arbitary $? value (decimal)
echo
echo 'test 1: All return codes are "as expected"'
echo  ======
 ((1==1)) && echo  " ((1==1)) rc=$? ..&&.. condition is true" || echo  " ((1==1)) rc=$? ..||.. condition is false"
  $0  0   && echo "  \$0  0   rc=$? ..&&.. condition is true" || echo "  \$0  0   rc=$? ..||.. condition is false"
 ((1!=1)) && echo  " ((1!=1)) rc=$? ..&&.. condition is true" || echo  " ((1!=1)) rc=$? ..||.. condition is false"
  $0  1   && echo "  \$0  1   rc=$? ..&&.. condition is true" || echo "  \$0  1   rc=$? ..||.. condition is false"
echo
echo 'test 2: Now throw in some "unexpected" errors into the first of the &&/|| pair' 
echo  ======
 ((1==1)) && (echo  " ((1==1)) rc=$? ..&&.. condition is true"; $0 1)  || echo  " ((1==1)) rc=$? ..||.. condition is false"
  $0  0   && (echo "  \$0  0   rc=$? ..&&.. condition is true"; $0 2)  || echo "  \$0  0   rc=$? ..||.. condition is false"
 ((1!=1)) && (echo  " ((1!=1)) rc=$? ..&&.. condition is true"; $0 3)  || echo  " ((1!=1)) rc=$? ..||.. condition is false"
  $0  1   && (echo "  \$0  1   rc=$? ..&&.. condition is true"; $0 4)  || echo "  \$0  1   rc=$? ..||.. condition is false"
echo
echo 'test 3: Now swap the order of && and || statements, using "as expected" return codes'
echo  ======
 ((1==1)) || echo  " ((1==1)) rc=$? ..||.. condition is true" && echo  " ((1==1)) rc=$? ..&&.. condition is false"
  $0  0   || echo "  \$0  0   rc=$? ..||.. condition is true" && echo "  \$0  0   rc=$? ..&&.. condition is false"
 ((1!=1)) || echo  " ((1!=1)) rc=$? ..||.. condition is true" && echo  " ((1!=1)) rc=$? ..&&.. condition is false"
  $0  1   || echo "  \$0  1   rc=$? ..||.. condition is true" && echo "  \$0  1   rc=$? ..&&.. condition is false"
echo
echo 'test 4: With the order of && and || statements still swapped, introduce "unexpected" errors into the first of the &&/|| pair' 
echo  ======
 ((1==1)) && (echo  " ((1==1)) rc=$? ..&&.. condition is true"; $0 1)  || echo  " ((1==1)) rc=$? ..||.. condition is false"
  $0  0   && (echo "  \$0  0   rc=$? ..&&.. condition is true"; $0 2)  || echo "  \$0  0   rc=$? ..||.. condition is false"
 ((1!=1)) && (echo  " ((1!=1)) rc=$? ..&&.. condition is true"; $0 3)  || echo  " ((1!=1)) rc=$? ..||.. condition is false"
  $0  1   && (echo "  \$0  1   rc=$? ..&&.. condition is true"; $0 4)  || echo "  \$0  1   rc=$? ..||.. condition is false"

exit 

Peter.O
sumber
1

mencoba

false && echo "hello"

dan

Salah ; gema "halo"

Lihat perbedaannya

Petrie Wong
sumber
0

Perintah (fungsi, dalam kasus skrip) setelah &&dijalankan tergantung pada RETVAL dari perintah pertama (fungsi, dalam kasus skrip). Ini memaksa perintah pertama untuk mengembalikan nilai 0, jika berhasil. Kami dapat memeriksa nilai kembali untuk menjalankan perintah lebih lanjut.

theTuxRacer
sumber