Grep-列出以正则表达式二进制字节序列开头的文件吗?

问题描述 投票:1回答:1

我想列出以某个字节序列开头的文件。我的想法因相同的行为而失败:

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,但是更喜欢直接grepping的速度,而不是大量的管道处理和循环遍历递归文件名以及环绕文本异常。 2-1 / 2年前的一个先前的问题“用Bash雕刻文件无法用grep找到十六进制值FFD8或FFD9”非常接近,但是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应该只使用\ A选项查看文件的前2个字节。

响应破折号的答案...

我考虑了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想法按可打印字节序列的预期工作,并且没有文档对某些字节值进行例外处理,或建议“面向行”的想法无效。看一下文件实用程序,它对于ID文件类型来说非常酷,但是我发现没有简单的方法可以递归目录并打印出路径/文件名,并且仅当它具有任意的前导字节序列时才每行一个。最后,我有点像bash家伙..是的。我需要学习更多perl和python ..但我确定通用bash / grep组合可以按文档所述工作。

regex perl grep binary hex
1个回答
1
投票

根据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,文本,不匹配)。它们都没有改变搜索的“性质”-它仍然会在lines

中查找正则表达式

要考虑的两个选项

  1. 如果要搜索“文件类型”(JPEG,PDF),请考虑使用file实用程序。它使用“魔术”数据库检查文件内容,并确定“文件类型”。它包括JPEG,PDF和更多类型。
  2. 使用其他实用程序(sed,perl),它可以更好地控制位置(例如,您可以将搜索限制在文件的第一行,等等)。您将需要花更多的时间来设置这些过滤器。就个人而言,如果您走这条路线,我会选择Perl。
© www.soinside.com 2019 - 2024. All rights reserved.