Làm cách nào để kiểm tra xem file1 có phải là tiền tố của file2 không?


13

Tôi có hai tệp có kích thước 124665 và 124858 tính bằng byte và muốn kiểm tra xem tệp1 có phải là tiền tố của tệp2 hay không.

Câu trả lời:


11

Giả sử bạn có kích thước của file1biến FILE1_SZheadviệc triển khai của bạn hỗ trợ -ctùy chọn (không chuẩn) :

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 Bạn có thể giải thích tại sao cmpsẽ tốt hơn diffở đây không?
Joseph R.

7
Bởi vì cmpso sánh byte với byte đơn giản và trả về ngay khi tìm thấy sự khác biệt, trong khi đó difflà một tiện ích văn bản sẽ sử dụng thuật toán phức tạp để hiển thị cho bạn tất cả sự khác biệt giữa hai tệp mà bạn không quan tâm.
Stéphane Chazelas

12

Nếu hệ thống của bạn có cmplệnh từ GNU diffutils, thì một tùy chọn là

cmp -n 124665 file1 file2

để so sánh tối đa 124665 byte đầu tiên của hai tệp và báo cáo nếu chúng khác nhau - hoặc, nói chung hơn

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

@StephaneChazelas Tôi đoán lần thứ hai ở đây nhưng sẽ tốt hơn nếu đề xuất $(stat -c %s file1)kích thước theo byte? Có wcthực sự mở và xử lý toàn bộ tập tin để có được số byte?
Steeldo

2
không, hầu hết các wctriển khai sẽ tối ưu hóa trường hợp đó và thực hiện fstat()(hoặc / và a lseek(SEEK_END)) vì vậy sẽ hiệu quả như nó có. Mặt khác, đó stat -clà GNU cụ thể.
Stéphane Chazelas

1
Mặc dù nếu bạn sẽ yêu cầu GNU cụ thể cmp, bạn có thể giả định hợp lý GNU stat.
Barmar

3

GNU cmpcó thể giải quyết vấn đề một cách dễ dàng hơn:

cmp file1 file2

Có bốn đầu ra có thể (chặn một số loại lỗi).

  • Không có đầu ra: các tập tin là giống hệt nhau.

  • cmp: EOF on file1: file1 là tiền tố của file2.

  • cmp: EOF on file2: file2 là tiền tố của file1.

  • file1 file2 differ: byte NNN, line MMM: Không phải là tiền tố của người khác.

Thật không may, điều này hơi khó sử dụng trong một tập lệnh, vì những trường hợp này dường như không được phân biệt trong mã thoát. Hơn nữa, các EOF on file1tin nhắn đi đến stderr, trong khi file1 file2 differtin nhắn đi đến thiết bị xuất chuẩn.

Tôi đoán rằng các phiên bản khác của cmpmột cái gì đó tương tự, nhưng tôi đã không kiểm tra.


1
cmpkhông phải là lệnh chỉ dành cho GNU và cũng không bắt nguồn từ đó, nó đã có trong phiên bản đầu tiên của Unix vào đầu những năm 70. Các -ntùy chọn là GNU cụ thể mặc dù.
Stéphane Chazelas

Bạn có thể làmcmp file1 file2 2>&1 | grep EOF on file1
David Z

@ StéphaneChazelas: Đó là sự thật. Tôi không có ý ám chỉ điều đó cmplà duy nhất với GNU, chỉ có điều GNU cmplà phiên bản duy nhất tôi đã thử. Tôi thêm một câu để làm rõ.
Nate Eldredge

@DavidZ: Vâng, bạn có thể, nhưng nó sẽ kém mạnh mẽ hơn một chút. Hãy tưởng tượng rằng bạn đang cố gắng thực hiện việc này với hai tệp do người dùng cung cấp và một trong số chúng được đặt tên file1và tệp còn lại được đặt tên file12. (Hoặc tệ hơn nữa, nếu tập tin thứ hai được đặt tên EOF on file1thì sao?) Việc giải quyết việc sử dụng mạnh mẽ cmpnày có lẽ rắc rối hơn nhiều so với việc viết chương trình 5 dòng rõ ràng trong C ...
Nate Eldredge

Tuy nhiên, có thể có bối cảnh trong đó một chương trình C không thực tế. Và không khó để làm cho nó khá mạnh mẽ, bởi vì đầu ra của cmprất hạn chế. Sử dụng -xtùy chọn trên grepđể khớp với toàn bộ dòng sẽ xử lý tất cả các trường hợp ngoại trừ trường hợp kỳ lạ nhất (ví dụ: dòng mới trong tên tệp).
David Z
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.