Bagaimana cara memeriksa apakah file1 adalah awalan dari file2?


13

Saya memiliki dua file dengan ukuran 124665 dan 124858 dalam byte dan ingin memeriksa apakah file1 adalah awalan dari file2 atau tidak.

Jawaban:


11

Andaikan Anda memiliki ukuran file1dalam variabel FILE1_SZdan headimplementasi Anda mendukung opsi (non-standar) -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 Bisakah Anda jelaskan mengapa cmplebih baik daripada di diffsini?
Joseph R.

7
Karena cmpmelakukan perbandingan byte ke byte yang sederhana, dan kembali segera setelah ia menemukan perbedaan, sementara itu diffadalah utilitas teks yang akan menggunakan algoritma yang kompleks untuk menunjukkan kepada Anda semua perbedaan antara dua file yang tidak Anda pedulikan.
Stéphane Chazelas

12

Jika sistem Anda memiliki cmpperintah dari GNU diffutils, maka satu opsi adalah

cmp -n 124665 file1 file2

untuk membandingkan paling banyak 124665 byte pertama dari dua file dan melaporkan jika mereka berbeda - atau, lebih umum

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

@StephaneChazelas Saya menebak-nebak diri saya di sini, tetapi apakah lebih baik menyarankan $(stat -c %s file1)ukuran dalam byte? Apakah wcbenar-benar membuka dan memproses seluruh file untuk mendapatkan jumlah byte?
steeldriver

2
tidak, sebagian besar wcimplementasi akan mengoptimalkan kasus itu dan melakukan fstat()(atau / dan lseek(SEEK_END)) jadi akan seefisien mungkin. Di sisi lain, itu stat -cadalah spesifik GNU.
Stéphane Chazelas

1
Meskipun jika Anda akan membutuhkan GNU-spesifik cmp, Anda mungkin menganggap GNU-specific stat.
Barmar

3

GNU cmpdapat memecahkan masalah dengan cara yang lebih mudah:

cmp file1 file2

Ada empat kemungkinan keluaran (kecuali beberapa jenis kesalahan).

  • Tidak ada output: file identik.

  • cmp: EOF on file1: file1 adalah awalan dari file2.

  • cmp: EOF on file2: file2 adalah awalan dari file1.

  • file1 file2 differ: byte NNN, line MMM: Tidak ada awalan dari yang lain.

Sayangnya ini agak canggung untuk digunakan dalam skrip, karena kasus-kasus ini tampaknya tidak dibedakan dalam kode keluar. Selain itu, EOF on file1pesan pergi ke stderr, sedangkan file1 file2 differpesan pergi ke stdout.

Saya menganggap bahwa versi lain cmpmelakukan sesuatu yang serupa, tetapi saya belum memeriksanya.


1
cmpbukan perintah GNU-only atau berasal di sana, itu sudah dalam versi pertama Unix di awal 70-an. The -npilihan adalah GNU spesifik sekalipun.
Stéphane Chazelas

Anda bisa melakukannyacmp file1 file2 2>&1 | grep EOF on file1
David Z

@ StéphaneChazelas: Itu benar. Saya tidak bermaksud mengatakan bahwa cmpitu adalah unik untuk GNU, hanya bahwa GNU cmpadalah satu-satunya versi yang saya coba. Saya menambahkan kalimat untuk menjelaskan.
Nate Eldredge

@ DavidZ: Ya, Anda bisa, tetapi itu menjadi sedikit kurang kuat. Bayangkan Anda mencoba melakukan ini dengan dua file yang disediakan oleh pengguna, dan salah satunya dinamai file1dan yang lain dinamai file12. (Atau lebih buruk lagi, bagaimana jika file kedua dinamai EOF on file1?) Memecahkan ini menggunakan kuat cmpmungkin jauh lebih sulit daripada menulis program 5-line yang jelas di C ...
Nate Eldredge

Mungkin ada konteks di mana program C tidak praktis. Dan itu tidak sulit untuk membuatnya cukup kuat, karena outputnya cmpsangat terbatas. Menggunakan -xopsi grepuntuk mencocokkan seluruh baris akan menangani semua kecuali kasus yang paling eksotis (misalnya baris baru dalam nama file).
David Z
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.