อะไรคือความแตกต่างของ -a และ -e ในนิพจน์เงื่อนไขของ bash?


12

จากman bash:

CONDITIONAL EXPRESSIONS
[...]
       -a file
              True if file exists.
[...]
       -e file
              True if file exists.
  1. แล้วอะไรคือความแตกต่างระหว่าง[ -a $FILE ]และ[ -e $FILE ]ถ้ามี?
  2. หากไม่มีความแตกต่างจริงเหตุใดจึงมีค่าสถานะสองค่าสำหรับจุดประสงค์เดียวกัน

มีเพียงนักพัฒนาเท่านั้นที่จะรู้ว่า # 2 --- เว้นแต่พวกเขาแบ่งปันการให้เหตุผลกับชุมชน
Belmin Fernandez

คำตอบ:


13

ในbashกับบริบทของสองtestคำสั่งอาร์กิวเมนต์-a fileและ-e fileเหมือนกัน แต่พวกเขามีความแตกต่างเพราะ-aเป็นผู้ประกอบการแบบไบนารี

-eunary ถูกกำหนดโดย POSIX แต่ไม่ใช่-aunary POSIX กำหนด-aไบนารีเท่านั้น(ดูทดสอบ POSIX)

POSIX กำหนดtestพฤติกรรมการขัดแย้งสามประการ:

3 ข้อโต้แย้ง:

  • ถ้า $ 2 เป็นไบนารีหลักให้ดำเนินการทดสอบไบนารีที่ $ 1 และ $ 3

  • หาก $ 1 คือ '!' ให้ปฏิเสธการทดสอบสองข้อโต้แย้งที่ $ 2 และ $ 3

  • หาก $ 1 คือ '(' และ $ 3 คือ ')' ให้ดำเนินการทดสอบ unary ที่ $ 2 บนระบบที่ไม่รองรับตัวเลือก XSI ผลลัพธ์จะไม่ถูกระบุหาก $ 1 คือ '(' และ $ 3 คือ ')'

  • มิฉะนั้นให้สร้างผลลัพธ์ที่ไม่ระบุ

ดังนั้น-aยังนำไปสู่ผลลัพธ์ที่แปลก:

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

-aถือเป็นผู้ประกอบการไบนารีในบริบทของสามข้อโต้แย้ง ดูทุบตีคำถามที่พบบ่อยคำถาม E1 POSIX ยังกล่าวถึงที่-aได้รับจาก KornShell แต่ถูกเปลี่ยนในภายหลัง-eเพราะมันทำให้เกิดความสับสนระหว่าง-aไบนารีและ-aunary

มีการเพิ่มฟังก์ชันหลัก -e ที่มีฟังก์ชันคล้ายกับที่ให้โดย C เชลล์เนื่องจากเป็นวิธีเดียวที่เชลล์สคริปต์จะค้นหาว่ามีไฟล์อยู่หรือไม่โดยไม่พยายามเปิดไฟล์ เนื่องจากการใช้งานได้รับอนุญาตให้เพิ่มประเภทไฟล์เพิ่มเติมสคริปต์แบบพกพาไม่สามารถใช้:

ทดสอบ -b foo -o -c foo -o -d foo -o -f foo -o -p foo

เพื่อค้นหาว่า foo เป็นไฟล์ที่มีอยู่หรือไม่ บนระบบ BSD ที่ผ่านมาการมีอยู่ของไฟล์สามารถกำหนดได้โดย:

ทดสอบ -f foo -o -d foo

แต่ไม่มีวิธีที่ง่ายในการพิจารณาว่าไฟล์ที่มีอยู่เป็นไฟล์ปกติ ข้อเสนอแรก ๆ ใช้ KornShell -a primary (ที่มีความหมายเหมือนกัน) แต่สิ่งนี้เปลี่ยนเป็น -e เพราะมีความกังวลเกี่ยวกับความน่าจะเป็นสูงของมนุษย์ที่ทำให้เกิดความสับสนหลัก -a กับตัวดำเนินการไบนารี

-aไบนารี่ถูกทำเครื่องหมายว่าล้าสมัยเพราะมันนำไปสู่การแสดงออกที่ไม่ชัดเจนซึ่งมีมากกว่า 4 ข้อโต้แย้ง ด้วยนิพจน์อาร์กิวเมนต์เหล่านี้> 4 POSIX จะกำหนดผลลัพธ์ที่ไม่ระบุ


เด็ดน่ารู้! ตอนนี้มันชัดเจนมากขึ้น :)!
polym

9

0.1 ดังนั้นอะไรคือความแตกต่างระหว่าง [-a $ FILE] และ [-e $ FILE] ถ้ามี?

ไม่มีความแตกต่างเลย

ในสาย505-507ในtest.cรุ่นทุบตี4.2.45(1)-release:

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

นั่นบ่งชี้ว่าไม่มีความแตกต่างที่แท้จริงระหว่างธงทั้งสอง

0.2 หากไม่มีความแตกต่างจริงเหตุใดจึงมีค่าสถานะสองค่าสำหรับจุดประสงค์เดียวกัน

ดูคำตอบของgnouc


3
บนมืออื่น ๆ ที่ได้รับว่า-aเป็นยังผู้ประกอบการบูลีน (และ) ในทุบตีดูเหมือนว่าข้อผิดพลาดที่มีแนวโน้มที่จะเพิ่มความหมายเพิ่มเติมที่ซ้ำซ้อนสมบูรณ์; ฉันคิดว่ามันเป็นเรื่องที่เกี่ยวข้องมากขึ้นในการเข้ากันได้บางส่วนการดำเนินงานอื่น ๆ และ / -eหรือเข้ากันได้กับรุ่นก่อนหน้านี้ที่ไม่ได้มี
celtschk

@celtschk - มันไม่ได้เป็น bugprone แต่ parser เปลือกอาจจะ POSIX ระบุ-aและ-obooleans [ test ]สำหรับ แต่เชลล์บางตัว(เหมือนbash)ดูดที่แยกอาร์กิวเมนต์จากโอเปอเรเตอร์และ[ test ]ผลลัพธ์ไม่น่าเชื่อถือ ตั้งแต่นั้นมา POSIX จึงต้องการให้เชลล์ที่สอดคล้องใด ๆ จัดการกับอาร์กิวเมนต์อย่างน้อย 4 อาร์กิวเมนต์ภายใน[ test ]วงเล็บเหลี่ยม
mikeserv

5

คำตอบที่ดีที่สุดที่ฉันพบคือคำถามนี้จากคำถาม StackOverflow:

-aเลิกใช้แล้วดังนั้นจึงไม่มีรายชื่ออยู่ใน manpage /usr/bin/testอีกต่อไป แต่ยังอยู่ในรายการสำหรับ bash -eใช้ สำหรับ single '[' the bash builtin จะทำงานเช่นเดียวกับtestbash builtin ซึ่งทำงานเหมือนกับ/usr/bin/[และ/usr/bin/test (อันหนึ่งคือ symlink ไปอีกอัน) หมายเหตุผลของการ-aขึ้นอยู่กับตำแหน่ง: file existsถ้ามันเป็นที่เริ่มต้นก็หมายความว่า andถ้ามันอยู่ในช่วงกลางของการแสดงออกสองก็หมายความตรรกะ

[ ! -a /path ] && echo existsไม่ทำงานเนื่องจากคู่มือทุบตีชี้ให้เห็นว่า-aถือเป็นผู้ประกอบการไบนารีที่นั่นและดังนั้นจึงไม่ได้แยกวิเคราะห์ข้างต้นเป็นnegate -a ..แต่เป็นif '!' and '/path' is true(ไม่ว่าง) ดังนั้นสคริปต์ของคุณจะแสดงผลออกมาเสมอ"-a"(ซึ่งจริง ๆ แล้วทดสอบไฟล์) และ"! -a"ที่จริงคือไบนารี andที่นี่

สำหรับ[[, -aไม่ได้ใช้เป็นไบนารีandอีกต่อไป ( &&จะใช้มี) เพื่อวัตถุประสงค์ที่เป็นเอกลักษณ์คือการตรวจสอบแฟ้มมี (ถึงแม้จะถูกเลิกใช้แล้ว) ดังนั้นการปฏิเสธจะทำในสิ่งที่คุณคาดหวัง

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