จะตรวจสอบว่า file1 เป็นคำนำหน้าของ file2 ได้อย่างไร?


13

ฉันมีสองไฟล์ที่มีขนาด 124665 และ 124858 ในหน่วยไบต์และต้องการตรวจสอบว่า file1 เป็นคำนำหน้าของ file2 หรือไม่

คำตอบ:


11

สมมติว่าคุณมีขนาดของfile1ตัวแปรFILE1_SZและheadการใช้งานของคุณรองรับ-cตัวเลือก(ที่ไม่ได้มาตรฐาน) :

if head -c "$FILE1_SZ" file2 | cmp -s - file1; then
    echo "file1 is a prefix of file2"
else
    echo "file1 is not a prefix of file2"
fi

@ StéphaneChazelasคุณช่วยอธิบายcmpได้diffไหมว่าทำไมถึงดีกว่าที่นี่
โจเซฟอาร์.

7
เนื่องจากcmpทำการเปรียบเทียบแบบไบต์ต่อไบต์แบบง่ายๆและจะส่งคืนทันทีที่พบความแตกต่างขณะที่diffยูทิลิตีข้อความจะใช้อัลกอริทึมแบบซับซ้อนเพื่อแสดงความแตกต่างระหว่างไฟล์ทั้งสองที่คุณไม่สนใจ
Stéphane Chazelas

12

หากระบบของคุณมีcmpคำสั่งจาก GNU แสดงdiffutilsตัวเลือกเดียวคือ

cmp -n 124665 file1 file2

เพื่อเปรียบเทียบสูงสุด 124665 ไบต์แรกของทั้งสองไฟล์และรายงานหากมีความแตกต่าง - หรือมากกว่าโดยทั่วไป

cmp -n "$(wc -c < file1)" file1 file2

@StephaneChazelas ฉันสองคาดเดาตัวเองที่นี่ แต่มันจะดีกว่าที่จะแนะนำ$(stat -c %s file1)สำหรับขนาดเป็นไบต์? ไม่wcจริงเปิดและประมวลผลไฟล์ทั้งหมดจะได้รับการนับไบต์?
ขับรถเหล็ก

2
ไม่wcการใช้งานส่วนใหญ่จะปรับให้เหมาะสมกรณีและทำfstat()(หรือ / และ a lseek(SEEK_END)) ดังนั้นจะมีประสิทธิภาพเท่าที่ได้รับ ในทางตรงกันข้ามนั่นstat -cคือ GNU เฉพาะ
Stéphane Chazelas

1
แต่ถ้าคุณกำลังจะต้อง GNU เฉพาะcmpคุณสมควรอาจคิด statGNU
Barmar

3

GNU cmpสามารถแก้ปัญหาด้วยวิธีที่ง่ายกว่า:

cmp file1 file2

มีเอาต์พุตที่เป็นไปได้สี่แบบ (ยกเว้นข้อผิดพลาดบางประเภท)

  • ไม่มีผลลัพธ์: ไฟล์เหมือนกัน

  • cmp: EOF on file1: file1 เป็นคำนำหน้าของ file2

  • cmp: EOF on file2: file2 เป็นคำนำหน้าของ file1

  • file1 file2 differ: byte NNN, line MMM: ทั้งสองเป็นคำนำหน้าของอื่น ๆ

น่าเสียดายที่นี่ไม่ค่อยน่าใช้ในสคริปต์เนื่องจากกรณีเหล่านี้ดูเหมือนจะไม่แตกต่างในรหัสออก นอกจากนี้EOF on file1ข้อความจะไปที่ stderr ในขณะที่file1 file2 differข้อความนั้นจะไปที่ stdout

ฉันคิดว่ารุ่นอื่น ๆcmpทำสิ่งที่คล้ายกัน แต่ฉันยังไม่ได้ตรวจสอบ


1
cmpไม่ใช่คำสั่งเดียวของ GNU และไม่ได้มีต้นกำเนิดมาจากมันมีอยู่แล้วในรุ่นแรกของ Unix ในต้นปี 70 -nตัวเลือกที่ GNU เฉพาะแม้ว่า
Stéphane Chazelas

คุณสามารถทำได้cmp file1 file2 2>&1 | grep EOF on file1
David Z

@ StéphaneChazelas: นั่นเป็นเรื่องจริง ฉันไม่ได้หมายความว่าcmpมันเป็นเอกลักษณ์ของ GNU เพียงแค่ GNU cmpเป็นรุ่นเดียวที่ฉันลอง ฉันเพิ่มประโยคเพื่อชี้แจง
Nate Eldredge

@DavidZ: ใช่คุณทำได้ แต่ได้รับน้อยกว่าเล็กน้อย ลองนึกภาพว่าคุณกำลังพยายามทำสิ่งนี้กับสองไฟล์ที่จัดทำโดยผู้ใช้และหนึ่งในนั้นมีชื่อfile1และอีกชื่อfile12หนึ่ง (หรือแย่ลงยังสิ่งที่ถ้าไฟล์ที่สองคือชื่อEOF on file1?) การแก้นี้ทนทานใช้cmpน่าจะเป็นปัญหามากขึ้นกว่าการเขียนโปรแกรมที่เห็นได้ชัด 5 บรรทัดใน C ...
เนท Eldredge

อาจมีบริบทที่โปรแกรม C ไม่สามารถใช้งานได้ และมันก็ไม่ใช่เรื่องยากที่จะทำให้มันมีความแข็งแกร่งพอสมควรเพราะผลลัพธ์ของcmpข้อ จำกัด นั้นแน่น การใช้-xตัวเลือกในgrepการจับคู่ทั้งบรรทัดจะดูแลทุกกรณียกเว้นกรณีที่แปลกใหม่ที่สุด (เช่นบรรทัดใหม่ในชื่อไฟล์)
David Z
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.