Grep - список файлов, которые начинаются с последовательности двоичных байтов регулярных выражений? - PullRequest
1 голос
/ 05 ноября 2019

Я хочу перечислить файлы, которые начинаются с определенной последовательности байтов. Мои идеи терпят неудачу с идентичным поведением:

grep -Rl $'\A\xff\xd8' .
grep -Rl \A$'\xff\xd8' .
grep -RlP "\A\xff\xd8" .

Тестовый файл, начинающийся с ff d8, не найден, в то время как найдено 3 других файла, которые имеют последовательность байтов в другом месте файла. Первые несколько байтов моего тестового файла подтверждаются с помощью hexdump -C.

00000000  ff d8 ff e0 00 10 4a 46  49 46 00 01 01 00 00 01  |......JFIF......|

Я нашел несколько «почти» ответов. Я исследовал hexdump, но предпочитаю скорость прямого поиска, а не множество операций с рекурсивными именами файлов и обходом текстовых исключений. Предыдущий вопрос 2-1 / 2 года назад "При вырезании файлов с помощью Bash не удается найти шестнадцатеричные значения FFD8 или FFD9 с помощью grep", но он очень близок, но LC_ALL = C не меняет поведения. Игра с -a и -b не меняет поведение.

Как правильно это сделать? Я использую GNU grep 3.1.

/// Дальнейшее изучение заставляет меня думать, что у grep может быть такая же проблема. Код ниже показывает, что 2-байтовая последовательность не найдена, когда она не в начале. Затем найдена 2-байтовая последовательность, когда она есть в начале. Также в реальном jpg-файле совпадение найдено, когда оно в начале. Пока все хорошо.

dell@DELL-E6440:~$ echo $'\xffThis is a short test file I\xff\xd8 made' > junk.txt
dell@DELL-E6440:~$ hexdump -C junk.txt | head -n1
00000000  ff 54 68 69 73 20 69 73  20 61 20 73 68 6f 72 74  |.This is a short|
dell@DELL-E6440:~$ LC_ALL=C grep -lP "\A\xff\xd8" junk.txt
dell@DELL-E6440:~$ echo $'\xff\xd8This is a short test file I\xff\xd8 made' > junk.txt
dell@DELL-E6440:~$ hexdump -C junk.txt | head -n1
00000000  ff d8 54 68 69 73 20 69  73 20 61 20 73 68 6f 72  |..This is a shor|
dell@DELL-E6440:~$ LC_ALL=C grep -lP "\A\xff\xd8" junk.txt
junk.txt
dell@DELL-E6440:~$ hexdump -C avoid-powered.jpg | head -n1
00000000  ff d8 ff e0 00 10 4a 46  49 46 00 01 01 00 00 01  |......JFIF......|
dell@DELL-E6440:~$ LC_ALL=C grep -lP "\A\xff\xd8" avoid-powered.jpg
avoid-powered.jpg
dell@DELL-E6440:~$ 

Итак, почему оно сопоставляется в файле большего размера, когда оно НЕ в начале? Сначала покажите, что файл без необходимой 2-байтовой последовательности сопоставляется. Затем сохраните только начало реального файла, и 2-байтовая последовательность должным образом не найдена.

dell@DELL-E6440:~$ cp 130913-SEMSA.pdf junk.txt
dell@DELL-E6440:~$ hexdump -C junk.txt | head -n1
00000000  25 50 44 46 2d 31 2e 34  0a 31 20 30 20 6f 62 6a  |%PDF-1.4.1 0 obj|
dell@DELL-E6440:~$ LC_ALL=C grep -lP "\A\xff\xd8" junk.txt
junk.txt
dell@DELL-E6440:~$ dd if=130913-SEMSA.pdf bs=10 count=1 of=junk.txt
1+0 records in
1+0 records out
10 bytes copied, 0.0062894 s, 1.6 kB/s
dell@DELL-E6440:~$ hexdump -C junk.txt | head -n1
00000000  25 50 44 46 2d 31 2e 34  0a 31                    |%PDF-1.4.1|
dell@DELL-E6440:~$ LC_ALL=C grep -lP "\A\xff\xd8" junk.txt
dell@DELL-E6440:~$

Что может быть в файле полного размера, который дает ложное совпадение? grep должен искать только первые 2 байта файла с параметром \ A.

Ответ на ответ dash-o ...

Я рассмотрел руководство grep v3.3 https://www.gnu.org/software/grep/manual/grep.html, который говорит,

-P Interpret patterns as Perl-compatible regular expressions (PCREs)

и руководство по регулярным выражениям Perl https://www.tutorialspoint.com/perl/perl_regular_expressions.htm говорит,

\A Matches beginning of string.

Кроме того, идея \ A работает так, как и должнопечатаемые последовательности байтов, и никакая документация не делает исключения для определенных значений байтов или предполагает, что «ориентированные на строки» должны отрицать эту идею. Глядя на файловую утилиту, довольно здорово идентифицировать типы файлов, но я не вижу простого способа рекурсировать каталоги и распечатывать путь / имя файла, по одному на строку, если и только если она имеет произвольную последовательность начальных байтов. Наконец, я вроде парня из bash ... да ... мне нужно больше изучать Perl и Python ... но я бы хотел, чтобы универсальная комбинация bash / grep работала, как описано в документации.

1 Ответ

1 голос
/ 06 ноября 2019

Согласно руководству grep, поддержка '\ A` не поддерживается, только для' ^ 'и' $ '

3.4 Anchoring
=============
The caret ‘^’ and the dollar sign ‘$’ are meta-characters that
respectively match the empty string at the beginning and end of a line.
They are termed “anchors”, since they force the match to be “anchored”
to beginning or end of a line, respectively.

Кроме того, напомним, что grep - это утилита поиска, ориентированная на строки. ,У него есть несколько опций для обработки двоичных файлов (--binary-files = binary, text, без соответствия). Ни один из них не меняет «природу» поиска - он все равно будет искать регулярное выражение в lines

Два варианта для рассмотрения

  1. Если вы ищете поиск по 'типы файлов »(JPEG, PDF), рассмотрите возможность использования утилиты file. Он использует «волшебную» базу данных для проверки содержимого файла и определения «типа файла». Он включает JPEG, PDF и другие типы.
  2. Используйте другую утилиту (sed, perl), которая позволяет лучше контролировать местоположение (например, вы можете ограничить поиск до первой строки файла и т. Д.). Вам нужно будет потратить больше на настройку этих фильтров. Лично я бы пошел с Perl, если вы выберете этот маршрут.
...