Как проверить, является ли 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текстовая утилита собирается использовать сложный алгоритм, чтобы показать вам все различия между двумя файлами, которые вас не интересуют.
— Стефан Шазелас

12

Если ваша система имеет cmpкоманду из GNU diffutils, то одна из опций

cmp -n 124665 file1 file2

сравнить не более первых 124665 байтов двух файлов и сообщить, отличаются ли они - или, в более общем случае,

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

@StephaneChazelas Я второй угадываю себя здесь, но было бы лучше предложить $(stat -c %s file1)размер в байтах? На wcсамом деле открыть и обработать весь файл, чтобы получить количество байтов?
— Steeldriver

2
нет, большинство wcреализаций оптимизирует этот случай и выполнит fstat()(или / и lseek(SEEK_END)), поэтому будет настолько эффективным, насколько это возможно. С другой стороны, это stat -cспецифично для GNU.
— Стефан Шазелас

1
Хотя, если вы собираетесь требовать специфичную для GNU cmp, вы можете разумно предположить специфичную для GNU stat.
— Бармар

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-only и она не возникла там, она была уже в первой версии Unix в начале 70-х годов. Эта -nопция специфична для GNU.
— Стефан Шазелас

Вы могли бы сделатьcmp file1 file2 2>&1 | grep EOF on file1
— Дэвид Z

@ StéphaneChazelas: это правда. Я не хотел подразумевать, что cmpэто уникально для GNU, просто GNU cmpбыла единственной версией, которую я пробовал. Я добавил предложение, чтобы уточнить.
— Нейт Элдредж

@DavidZ: Да, вы могли бы, но это становится немного менее надежным. Представьте, что вы пытаетесь сделать это с двумя файлами, предоставленными пользователем, и один из них назван, file1а другой назван file12. (Или, что еще хуже, что, если второй файл будет назван EOF on file1?) Решить это с помощью надежного использования cmp, вероятно, гораздо сложнее, чем написать очевидную 5-строчную программу на C ...
— Нейт Элдридж

Однако могут быть ситуации, когда программа на С не практична. И это не так сложно сделать достаточно надежным, потому что выходные данные cmpочень сильно ограничены. Использование -xопции on, grepчтобы соответствовать всей строке, позаботится обо всех, кроме самых экзотических случаях (например, новые строки в имени файла).
— Дэвид З
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.