递归搜索二进制文件的目录是否为十六进制序列?

时间:2015-05-15 13:32:11

标签: shell zsh binaryfiles hexdump find-util

我用来搜索某些十六进制值的当前命令(比如0A 8b 02)涉及:

find . -type f -not -name "*.png" -exec xxd -p {} \; | grep "0a8b02" || xargs -0 -P 4

考虑到以下目标,是否有可能改善这一目标:

  • 递归搜索文件
  • 显示偏移和文件名
  • 排除某些带有特定扩展名的文件(以上示例不会搜索.png个文件)
  • 速度:搜索需要处理200,000个文件(大约50KB到1MB),直接总计~2GB。

如果xargs正在为4个处理器正常工作,我不太自信。此外,当grep找到匹配项时,我在打印文件名时遇到了困难,因为它是从xxd传来的。有什么建议吗?

1 个答案:

答案 0 :(得分:2)

如果:

  • 你有 GNU grep
  • 并且您搜索的十六进制字节绝不包含换行符(0xa [1]
    • 如果它们包含NUL(0x),则必须通过文件(grep)而不是直接参数提供-f搜索字符串。

使用搜索0e 8b 02

的示例,以下命令可以帮助您实现目标
LC_ALL=C find . -type f -not -name "*.png" -exec grep -FHoab $'\x{0e}\x{8b}\x{02}' {} + |
  LC_ALL=C cut -d: -f1-2

grep命令生成输出行,如下所示:

<filename>:<byte-offset>:<matched-bytes>

其中LC_ALL=C cut -d: -f1-2会缩减为<filename>:<byte-offset>

命令几乎 BSD grep一起使用,除了报告的字节偏移总是 start 的行模式匹配。
换句话说:如果文件中没有换行符,则字节偏移量才会正确。
此外,BSD grep不支持将NUL(0x0)个字节指定为搜索字符串的一部分,即使通过-f的文件提供也不支持。

  • 请注意,基于使用grep&#,没有并行处理,但只有少数 find次调用39; s -exec ... +,与xargs一样,会同时传递尽可能多的文件名到命令行grep
  • 通过让grep直接搜索字节序列,不需要xxd
    • 序列被指定为ANSI C-quoted string,这意味着转义序列被 shell 扩展为文字,使得Grep能够搜索结果字符串作为文字(通过-F),这更快 链接的文章来自bash手册,但它们也适用于zsh(以及ksh)。
      • GNU Grep的替代方法是使用-P(支持PRCE,Perl兼容的正则表达式)和非预扩展的转义序列,但这将是更慢:{{ 1}}
    • grep -PHoab '\x{0e}\x{8b}\x{02}'确保LC_ALL=C将每个字节视为自己的字符,而不应用任何编码规则。
    • grep将搜索字符串视为文字(而不是正则表达式)
    • -F将相关的输入文件名添加到每个输出行;请注意,当给出多于1个文件名参数时,Grep会隐式执行此操作
    • -H仅报告匹配的字符串(字节序列),而不是整行(无论如何,行的概念在二进制文件中没有意义) [2]
    • -o将二进制文件视为文本文件(如果不是这样,Grep只会为匹配的二进制输入文件打印文本-a
    • Binary file <filename> matches报告匹配的字节偏移量

如果在给定的输入文件中找到最多 1 匹配就足够了,请添加-b

[1]无法使用换行符,因为Grep总是将搜索模式字符串中的换行符视为分隔多个搜索模式。另外,Grep是基于 line 的,所以你不能跨行匹配; GNU Grep的-m 1选项将输入分割为NUL字节可能有所帮助,但前提是您的搜索字节序列不包含NUL字节;您还必须将正则表达式中的转义序列-null-data结合起来表示您的字节值 - 因为您需要使用转义符序列-P代替实际换行符。

需要

[2] \n使-o报告匹配的字节偏移量,而不是行开头的字节偏移量(如上所述,不幸的是,BSD Grep 总是做后者);此外,仅在此处报告匹配本身是有益的,因为尝试打印整行将导致不可预测的长输出行,因为二进制文件中没有行的概念;但是,无论哪种方式,从二进制文件输出字节都可能导致终端出现奇怪的渲染行为。

相关问题