Bash 如何从Linux命令行检查二进制文件是否包含在另一个二进制文件中?

Bash 如何从Linux命令行检查二进制文件是否包含在另一个二进制文件中?,bash,grep,posix,gnu-coreutils,Bash,Grep,Posix,Gnu Coreutils,基本上我想要一个“以二进制字符串为模式的多行grep” 例如: printf '\x00\x01\n\x02\x03' > big.bin printf '\x01\n\x02' > small.bin printf '\x00\n\x02' > small2.bin 那么,以下内容应适用: small.bin包含在big.bin small2.bin不包含在big.bin 我不想将文件转换为ASCII十六进制表示形式,如图所示xxd,例如at:,因为这感觉很浪费 理想情

基本上我想要一个“以二进制字符串为模式的多行grep”

例如:

printf '\x00\x01\n\x02\x03' > big.bin
printf '\x01\n\x02' > small.bin
printf '\x00\n\x02' > small2.bin
那么,以下内容应适用:

  • small.bin
    包含在
    big.bin
  • small2.bin
    不包含在
    big.bin
我不想将文件转换为ASCII十六进制表示形式,如图所示
xxd
,例如at:,因为这感觉很浪费

理想情况下,该工具应该处理不适合内存的大型文件

请注意,以下尝试无效

grep-f
匹配不应该匹配的位置,因为它必须拆分换行符:

grep -F -f small.bin big.bin
# Correct: Binary file big.bin matches
grep -F -f small2.bin big.bin
# Wrong: Binary file big.bin matches
$(cat)
中的Shell替换失败,因为它是失败的,所以字符串在第一次
0
时被截断

grep -F "$(cat small.bin)" big.bin
# Correct: Binary file big.bin matches
grep -F "$(cat small2.bin)" big.bin
# Wrong: Binary file big.bin matches
有人问了一个C问题:但是是否可以使用任何广泛可用的CLI(希望是POSIX或GNU coreutils)工具

值得注意的是,实现一个非朴素的算法,例如,并不完全是微不足道的

我可以按如下方式编写一个工作的Python one liner,但它不适用于不适合内存的文件:

grepbin() ( python -c 'import sys;sys.exit(not open(sys.argv[1]).read() in open(sys.argv[2]).read())' "$1" "$2" )
grepbin small.bin big.bin && echo 1
grepbin small2.bin big.bin && echo 2
我还可以在GitHub上找到以下两个工具:

  • 在C语言中,可使用(惊人:-)安装:

  • 带锈,可与以下部件一起安装:

    cargo install bgrep
    
但它们似乎不支持从文件中获取模式,您可以在命令行上以十六进制ASCII格式提供输入。我可以使用:

bgrep $(xxd -p small.bin | tr -d '\n') big.bin
因为用
xxd
转换小文件并不重要,但这不是很好

无论如何,如果我要实现该特性,我很可能会将其应用到上面的Rust库中

bgrep还提到:

在Ubuntu 20.10上测试

如何从Linux命令行检查二进制文件是否包含在另一个二进制文件中

POSIX可移植的方法是使用
od
转换为十六进制,然后使用
grep
检查子字符串,以及中间的一些
sed
脚本

通常的正常便携方式是使用
xxd
而不是
od

xxd -p small.bin | tr -d '[ \n]' > small.bin2
xxd -p big.bin | tr -d '[ \n]' > big.bin2
grep -F -f small.bin2 big.bin2
使用
busybox
alpine
上的
docker
中进行了良好测试

但是:

我不想将文件转换为ASCII十六进制表示形式,如图所示

那么您就不能在shell中使用二进制文件了。选择另一种语言。Shell是专门为解析好看的人类可读字符串而创建的—对于其他任何东西,它都是非常令人不愉快的,对于零字节的文件
xxd
是您键入的第一件事

我可以编写一个工作的Python一行程序,如下所示

awk
也是POSIX,在任何地方都可以使用-我相信在
awk
方面更熟练的人可能会来编写python脚本的1:1,但是:

但它不适用于不适合内存的文件:

grepbin() ( python -c 'import sys;sys.exit(not open(sys.argv[1]).read() in open(sys.argv[2]).read())' "$1" "$2" )
grepbin small.bin big.bin && echo 1
grepbin small2.bin big.bin && echo 2
所以,写一个不同的算法,它不会这样做

总的来说,当给出不使用
xxd
(或
od
)将零字节二进制文件转换为十六进制表示的约束时:

是否可以使用任何广泛可用的CLI(希望是POSIX或GNU coreutils)工具

不,写你自己的程序。您也可以用
perl
编写,它有时在没有
python
的机器上可用

如何从Linux命令行检查二进制文件是否包含在另一个二进制文件中

POSIX可移植的方法是使用
od
转换为十六进制,然后使用
grep
检查子字符串,以及中间的一些
sed
脚本

通常的正常便携方式是使用
xxd
而不是
od

xxd -p small.bin | tr -d '[ \n]' > small.bin2
xxd -p big.bin | tr -d '[ \n]' > big.bin2
grep -F -f small.bin2 big.bin2
使用
busybox
alpine
上的
docker
中进行了良好测试

但是:

我不想将文件转换为ASCII十六进制表示形式,如图所示

那么您就不能在shell中使用二进制文件了。选择另一种语言。Shell是专门为解析好看的人类可读字符串而创建的—对于其他任何东西,它都是非常令人不愉快的,对于零字节的文件
xxd
是您键入的第一件事

我可以编写一个工作的Python一行程序,如下所示

awk
也是POSIX,在任何地方都可以使用-我相信在
awk
方面更熟练的人可能会来编写python脚本的1:1,但是:

但它不适用于不适合内存的文件:

grepbin() ( python -c 'import sys;sys.exit(not open(sys.argv[1]).read() in open(sys.argv[2]).read())' "$1" "$2" )
grepbin small.bin big.bin && echo 1
grepbin small2.bin big.bin && echo 2
所以,写一个不同的算法,它不会这样做

总的来说,当给出不使用
xxd
(或
od
)将零字节二进制文件转换为十六进制表示的约束时:

是否可以使用任何广泛可用的CLI(希望是POSIX或GNU coreutils)工具


不,写你自己的程序。您也可以在
perl
中编写它,它有时在没有
python

rep-f匹配的机器上可用,因为它必须拆分换行符:
,并且还解析regex<代码>grep“$(cat small.bin)”不仅在零字节时失败
grep
需要一个正则表达式。请注意,您的
是否可以使用任何广泛可用的CLI
进入“寻找工具推荐”栏。@KamilCuk true,为非正则表达式添加了
-F
。如果它关闭,我会在其他地方发布,通常的过程。
“$(带空的cat文件)”
会设置自己失败,因为NUL不能存储在C字符串中,bash中的所有字符串都是NUL分隔的C字符串。就这一点而言,如果
grep
使用能够包含NUL文本的字符串,我会非常惊讶——不,惊讶——这将是构建一个版本的更合理的开始