ตรรกะและในสคริปต์ทุบตี


10

ฉันมีifในสคริปต์ทุบตีของฉันที่ต้องตรวจสอบว่า EITHER ของ 2 ไฟล์ที่มีอยู่หากพวกเขาไม่อยู่มันควรจะสะท้อน

รหัสฉันมี:

if [[ ! -f /etc/benchmarking/code ]] && [[ ! -f /etc/benchmarking/code.class ]]; then
 echo "match"
fi

แต่นี่ดูเหมือนจะไม่ทำงานด้วยเหตุผลบางอย่าง

ฉันแน่ใจว่า 110% ว่าไม่มีไฟล์ 2 ไฟล์นี้ ฉันไม่ได้รับข้อผิดพลาดใด ๆ ifมันก็ไม่ได้ใส่

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


ฉันไม่คิดว่าคำตอบใด ๆ ที่โพสต์ตอบคำถาม จะเกิดอะไรขึ้นเมื่อคุณลองทำแบบทดสอบแยกกัน ทำ[[ ! -f /etc/.../... ]]; echo $?เพื่อแต่ละ
jw013

คำเตือน : [[ -f xxx ]]ผลตอบแทนจริงถ้า xxx มีอยู่และเป็นไฟล์ปกติ (หรือ symlink ไปยังไฟล์ปกติ) มันจะคืนค่าเท็จหากไม่มีอยู่หรือไม่สามารถบอกได้ว่ามีอยู่หรือไม่หรือมีอยู่ แต่ไม่ใช่ไฟล์ปกติ (ไดเรกทอรี, ไพพ์, อุปกรณ์, ซ็อกเก็ต ... ) หรือถ้าเป็น symlink ไปยังไฟล์ที่ไม่มีอยู่หรือไม่สามารถบอกได้ว่ามีอยู่หรือไม่หรือไม่ใช่ไฟล์ปกติ ... [[ -e $file ]] || [[ -L $file ]]ใกล้ถึงการทดสอบการมีอยู่ ls -d -- "$file" > /dev/null 2>&1อยู่ใกล้ยิ่งขึ้น และตามกฎแล้วการทดสอบประเภทนี้นำไปสู่สภาพการแข่งขัน อาจจะมีวิธีอื่น
Stéphane Chazelas

คำตอบ:


12

หากคุณต้องการอย่างใดอย่างหนึ่งแล้วคุณต้องการไม่ได้ORAND

if [[ ! -f /etc/benchmarking/code ]] || [[ ! -f /etc/benchmarking/code.class ]]; then
 echo "match"
fi
  • สิ่งนี้จะตรงกันหากไฟล์ใดไฟล์หนึ่งหรือทั้งสองไฟล์หายไป
  • รหัสของคุณจะพิมพ์ก็ต่อmatchเมื่อไม่มีทั้งคู่

แต่คุณพูดว่า:

ฉันแน่ใจว่า 110% ว่าไม่มีไฟล์ 2 ไฟล์นี้ ฉันไม่ได้รับข้อผิดพลาดมันก็ไม่ได้ป้อนถ้า

ดังนั้นคำพูดของคุณขัดแย้งกับตัวเอง อย่างน้อยหนึ่งไฟล์เหล่านั้นจะต้องอยู่ถ้าคุณกำลังเรียกว่ารหัส

หากคุณต้องการที่จะเห็นว่าคุณคำสั่งการประเมินการทำงานด้วยif-x

#!/bin/bash -x
if [[ ! -f /etc/benchmarking/code ]] && [[ ! -f /etc/benchmarking/code.class ]]; then
 echo "match"
fi

จากนั้นคุณจะเห็นการดำเนินการ

$ ./test.sh
+ [[ ! -f /etc/benchmarking/code ]]
+ [[ ! -f /etc/benchmarking/code.class ]]
+ echo match
match
$ 

ฉันต้องการให้เสียงสะท้อน "จับคู่" หากไม่มีไฟล์อยู่หากมีอยู่ก็ไม่ได้พิมพ์ตรงกัน ฉันจะลองกับ -x
Peppercat101

ในกรณีนั้นรหัสเดิมของคุณควรจะถูกต้อง และมันใช้งานได้จริงสำหรับฉัน
บาฮามาต

3

ไม่ควรเป็นแบบนี้เหรอ? A คือไฟล์หรือ B เป็นไฟล์จากนั้น blabla

if [[ -f /etc/benchmarking/code ]] || [[ -f /etc/benchmarking/code.class ]]; 
then  
  echo "match"
fi

3

สิ่งนี้อาจใช้ได้กับสิ่งที่คุณพยายามทำ วงเล็บเหลี่ยมไม่ได้ใช้กันทั่วไปในปัจจุบันด้วยการทุบตี แต่นี่ก็ยังเป็นตัวเลือก การใช้ '-o' เป็นการดำเนินการ "หรือ" และ "!" ได้อย่างมีประสิทธิภาพ ปฏิเสธเงื่อนไข

var=/etc/benchmarking/code
[ ! -f ${var} -o -f {var}.class ] && echo "match"

ไม่เคยใช้ใน[ bashนอกเหนือจากนั้นฉันไม่สามารถดูว่าสิ่งนี้ตอบคำถาม
jw013

[ ! -f ${var} -a ! -f {var}.class ] && echo "match"มันควรจะเป็น. ภารกิจคือ: หากพวกเขา (ทั้งคู่) ไม่มีตัวตนมันควรจะecho matchเป็น
hschou

0

รหัสของคุณตรงตามความต้องการของคุณ: มันจะพิมพ์ออกmatchมาหากไม่สามารถหาไฟล์ใดไฟล์หนึ่งได้

ดังนั้นเหตุผลที่matchไม่ถูกพิมพ์อยู่ที่อื่น คุณควรยืนยันว่ามีการเข้าถึงบล็อกโค้ดซึ่งคุณสามารถทำได้โดยการล้อมรอบด้วยข้อความดีบั๊กสองสามข้อความ ตัวอย่างเช่นนี้:

echo '@ About to enter if...fi block'
if [[ ! -f /etc/benchmarking/code ]] && [[ ! -f /etc/benchmarking/code.class ]]; then
 echo "match"
fi
echo '@ Finished if...fi block'

การตั้งค่าตามปกติของฉันคือการดีบั๊กข้อความเพื่อไปยังstderrเพื่อหลีกเลี่ยงการขัดจังหวะการไหลของข้อมูลไปยังstdoutแต่ฉันได้หลีกเลี่ยงที่นี่เพราะคุณบอกว่าคุณเป็นมือใหม่ นี่คือตัวอย่างหนึ่งที่แสดงว่าคุณสามารถเขียนถึงstdout ได้อย่างไร :

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