อันไหนดีกว่า: ใช้; หรือ && เพื่อรันหลายคำสั่งในหนึ่งบรรทัด?


427

ในบทเรียนและวิธีการฉันมักจะเห็นคำสั่งรวมกัน ตัวอย่างเช่น

sudo apt-get update && sudo apt-get install pyrenamer

ดูเหมือนจะมีสี่การเชื่อมต่อเป็นไปได้: &, &&, และ|| ;แม้ว่า& ตัวเชื่อมต่อนั้นจะชัดเจนสำหรับฉัน (มันส่งกระบวนการไปยังพื้นหลังและทำให้เทอร์มินัลว่าง) แต่ก็ไม่ชัดเจนว่าความแตกต่างระหว่าง&&และ;คืออะไร และฉันไม่รู้||จนกระทั่งถึงความคิดเห็นของ Kaya

คำถามต่อไปนี้จะจัดการกับความแตกต่างระหว่างตัวเชื่อมต่อทั้งสอง แต่ส่วนใหญ่ทำในความคิดเห็น:

ดังนั้นนี่คือคำถามที่เกี่ยวข้องจำนวนหนึ่ง:

  1. ความแตกต่างระหว่าง;และ&&คืออะไร?
  2. เมื่อใดที่คุณควรใช้ตามลำดับ มันจะเป็นการดีถ้าได้เห็นการใช้งานบางกรณี: ถ้าฉันต้องการเรียกใช้คำสั่งแล้วหลังจากปิดคอมพิวเตอร์ฉันควรเลือกขั้วต่อไหน?
  3. ข้อดีและอันตรายของพวกเขาคืออะไร Robie Basakกล่าวถึงความคิดเห็นในคำตอบนี้ว่าคำสั่งเช่นcd /somewhere_else; rm -Rf *นั้นอาจมีผลที่ตามมาทำลายหากองค์ประกอบแรกในห่วงโซ่คำสั่งล้มเหลวตัวอย่างเช่น
  4. หากเกี่ยวข้องพวกเขามาจากไหน

7
มีตัวเชื่อมต่ออื่นที่คุณอาจไม่เจอ: ||เป็นเช่นเดียวกับ&&ยกเว้นว่าจะเรียกใช้งานคำสั่งที่สองเฉพาะถ้าตัวแรกออกจากสถานะที่ไม่เป็นศูนย์ (ไม่สำเร็จ)
Kaya

4
นอกจากนี้ยังทราบว่าการทำงานสคริปต์ของคุณกับจะหยุดสคริปต์บนความล้มเหลวเช่นถ้าคำสั่งทั้งหมดที่ถูกเชื่อมต่อกับset -e &&
choroba


3
ไม่มีใครตอบคำถามที่ 4 ... ฉันสงสัยว่าพฤติกรรมของ && และ || ได้รับแรงบันดาลใจจากภาษาซี ในกรณีของ (x && y) ถ้า x ประเมินเป็นเท็จนิพจน์ทั้งหมดจะต้องเป็นเท็จเพื่อให้คอมไพเลอร์สามารถปรับการประเมิน y ให้เหมาะสมในกรณีที่มีราคาแพง มาตรฐาน C และ C ++ ที่ทันสมัยต้องการการเพิ่มประสิทธิภาพนี้จริง ๆดังนั้นโปรแกรมสามารถสันนิษฐานได้ว่า y จะไม่ถูกประเมินถ้า x เป็นเท็จ ตัวอย่างเช่น (ptr && ptr-> วัน> 31) จะไม่ผิดพลาดแม้ว่า ptr จะเป็นโมฆะ นอกจากนี้ใน C งบลงท้ายด้วย; ไม่ว่าจะมีคำสั่งอื่นในบรรทัดเดียวกันหรือไม่ก็ตาม
Kevin

คำตอบ:


771

cheatsheet:

A; B    # Run A and then B, regardless of success of A
A && B  # Run B if and only if A succeeded
A || B  # Run B if and only if A failed
A &     # Run A in background.

19
และแน่นอนA & B &: รัน A ในพื้นหลังจากนั้นรัน B ในแบ็คกราวน์ (โดยไม่คำนึงถึงความสำเร็จ) และกลับไปควบคุมเชลล์ วิธีนี้ใช้ได้ผลเหมือนกันกับการรันทั้งสองกระบวนการในเวลาเดียวกัน
การชดเชย จำกัด

4
เป็นไปได้หรือไม่ที่จะพูดว่า: รัน a เป็นแบ็คกราวด์, ตามด้วย b เป็นแบ็คกราวน์เฉพาะในกรณีที่ใช้งานได้? (ฉันเดา &&&?)
user230910

15
@ user230910: (A && B) &ที่จะเป็น
leftaroundabout

5
คุณสามารถอ้างอิงเอกสารที่เชื่อถือได้สำหรับสิ่งนี้ได้หรือไม่?
Jaime Hablutzel

@ แจ็คเมื่อดำเนินการจาก Cronjob มันไม่ได้เป็นไปตามกฎนี้ความคิดใดทำไม? สำหรับไฟล์ไพ ธ อน
CodeGuru

77

&&รันคำสั่งที่สองเฉพาะหากคำสั่งแรกที่ออกด้วยสถานะ 0 (สำเร็จ) ;รันทั้งสองคำสั่งแม้ว่าคำสั่งแรกจะออกด้วยสถานะที่ไม่ใช่ศูนย์

ตัวอย่างของคุณที่มี&&สามารถถอดความได้เท่ากับ

if sudo apt-get update ; then
    sudo apt-get install pyrenamer
fi

ขอบคุณ ฉันได้อัปเดตคำถามเพื่อให้แน่ใจว่าคำถามย่อยที่แตกต่างกันสามารถแยกแยะได้ง่าย
don.joey

5
@ ส่วนบุคคล: คุณควรใช้;หากคำสั่งที่สองไม่ต้องการให้คำสั่งก่อนหน้านี้ประสบความสำเร็จ
choroba

31

การใช้;จะดำเนินการคำสั่งโดยไม่คำนึงว่าคำสั่งแรกจะสำเร็จหรือไม่

ใช้&&execute คำสั่งที่ 2 เฉพาะเมื่อคำสั่งแรกดำเนินการประสบความสำเร็จ (สถานะ 0)

ทั้งสองใช้ในมุมมองที่แตกต่างกัน เช่นเดียวกับกระบวนการที่ยาวกว่าพูดสำหรับการติดตั้งที่คุณต้องการรวบรวมและติดตั้ง make && make installคุณควร ดังนั้นการติดตั้งจะทำงานก็ต่อเมื่อmakeสำเร็จ

ดังนั้นสำหรับคำสั่งที่ขึ้นต่อกันคุณควรใช้ &&

Wring bash หรือคำสั่งที่มีคำสั่งอิสระใช้ ;

ดังนั้นหากคุณต้องการปิดเครื่องคอมพิวเตอร์แม้งานแรกจะล้มเหลวในการใช้งาน;แต่หากต้องการประสบความสำเร็จอย่างสมบูรณ์ในการทำงานครั้งแรกให้เริ่มใช้งานเครื่องให้ปิดเครื่อง&&


14

a ; bจะทำงาน b โดยไม่คำนึงถึงสถานะทางออกของ a && bจะรัน b เฉพาะในกรณีที่ประสบความสำเร็จ

นี่เป็นสิ่งที่จำเป็นและเพียงพอที่จะตอบคำถาม 3 ข้อแรก โดยเฉพาะอย่างยิ่ง 2 กว้างเกินไปและไม่สามารถให้คำตอบที่ชัดเจน "หนึ่ง" - ทางออกที่ดีที่สุดของคุณคือการตัดสินใจในแต่ละกรณี

สำหรับคำถามที่ 4: พวกเขากำลังไวยากรณ์ทุบตี

ไม่มีอันตรายที่แท้จริงในการใช้อย่างใดอย่างหนึ่ง คำจำกัดความข้างต้นก็เพียงพอแล้ว หมายความว่าคุณจะเขียน&&เมื่อbมีผลกระทบโดยไม่ตั้งใจหากaไม่ประสบความสำเร็จ ไม่จำเป็นต้องมีกฎหรือคำอธิบายเพิ่มเติม IMHO


1

; B # Run A และ B โดยไม่คำนึงถึงความสำเร็จของ A

A & B # รัน B ถ้าหาก A ประสบความสำเร็จเท่านั้น

A | | B # Run B ถ้าหาก A ล้มเหลว

A & # Run A ในพื้นหลัง

กฎง่ายๆที่ดีมาก ฉันจะเพิ่มว่าในบางกรณีการใช้คำสั่งเหล่านี้ใน subshell เหมาะสมเมื่อเราต้องการพิจารณาพวกเขาเป็นหน่วยเดียวหรือเราไม่ต้องการคู่ผลลัพธ์การดำเนินการบางอย่างกับเชลล์ปัจจุบัน

ตัวอย่าง:

- สร้างเอาต์พุตของสองคำสั่ง:

(ls foo; ls bar) > single-result.txt

- เข้าสู่ไดเรกทอรีและดำเนินการคำสั่งจากที่นั่นในขณะที่ไม่เปลี่ยนไดเรกทอรีปัจจุบันของเชลล์:

(cd target-directory && jar -xf ../my-jar)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.