4

我用来搜索一些十六进制值(比如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. 有什么建议么?

4

1 回答 1

4

如果:

  • 你有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一起使用,除了报告的字节偏移量总是与模式匹配的行的开头
换句话说:仅当文件中的匹配项之前没有换行符时,字节偏移量才会正确
此外,BSDgrep不支持将 NUL ( 0x0) 字节指定为搜索字符串的一部分,即使通过带有-f.

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

如果在给定的输入文件中最多可以找到1 个-m 1匹配项,则添加.


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

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

于 2015-05-15T21:29:05.643 回答