Як перевірити, чи є 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()(або / і a 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, і не зародилася там, вона була вже в першій версії Unix на початку 70-х. Цей -nваріант є специфічним для GNU.
Стефан Шазелас

Можна зробитиcmp file1 file2 2>&1 | grep EOF on file1
David Z

@ StéphaneChazelas: Це правда. Я не мав на увазі, що це cmpбуло унікальним для GNU, просто GNU cmpбула єдиною версією, яку я спробував. Я додав речення, щоб уточнити.
Нейт Елдредж

@DavidZ: Так, можна, але він стає менш надійним. Уявіть, що ви намагаєтеся зробити це з двома файлами, наданими користувачем, і один з них названий, file1а другий - ім'ям file12. (Або ще гірше, що, якщо другий файл буде названий EOF on file1?) Вирішення цього надійного використання cmp, ймовірно, набагато більше проблем, ніж написання очевидної 5-рядкової програми на C ...
Nate Eldredge

Можливо, є контексти, коли програма C не є практичною. І зробити це досить міцним не так важко, оскільки вихід cmpнастільки сильно обмежений. Використовуючи -xопцію "Увімкнути" grepдля відповідності всьому рядку, ви піклуєтесь про всі, крім самих екзотичних випадків (наприклад, нові рядки у назві файлу).
David Z
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.