Grep,但适用于二进制文件

Grep,但适用于二进制文件

我有数据恢复软件生成的图像文件的片段。我怀疑完整的原件位于我的家庭文件服务器上的某个地方。

如果这是文本文件的片段,我可以抓取一个看起来独特的片段,运行grep -r -l -F,并在几个小时后返回以获得答案。然而,由于这是一个二进制文件,它有各种grep不喜欢的东西(例如空字节),即使我可以克服这个问题,我也不知道如何提供grep无效的输入UTF-8。

我如何搜索原文,最好不编写自己的搜索程序?

(这不是重复的这个问题:尽管标题听起来很可能,但它是关于在二进制文件中查找字符串,我在二进制文件中查找二进制数据。)

答案1

我会做什么:

grep -a -r -l -F <fixed string> .

-a, --text
处理二进制文件,就像它是文本一样;这相当于 --binary-files=text 选项。

或者

find . -type f -exec sh -c '
    strings "$1" | grep -lF <fixed pattern>
' sh {} \;
 

strings - 打印文件中可打印字符的序列

答案2

你可以首先使用转储二进制文件OD:

我建议使用 -x 和 -w256 选项来减少文件大小和行数,以最大限度地提高 grep 效率,并且必须使用 -A n 选项来删除不必要的偏移地址,让我们:

od -x -A n -w256 yourbinary_fragment > pattern.txt

您还可以积极使用 -j -N 和 -w 选项,甚至重新编辑pattern.txt,以将行数减少到严格的最低限度。 (为了显着减轻grep的工作)

然后查找与模式匹配的文件自己被抛弃后

find . -type f -exec sh -c '
    od -x -A n -w256 "$1" | grep -lFf pattern.txt
' sh {} \;

如果将您的计算机用于其他目的,我建议对该进程进行 SCHED_BATCH。

答案3

使用perlSys::Mmap 模块(在libsys-mmap-perlDebian 上的包中):

fragment=/path/to/your/fragment
size=$(( $(wc -c < "$fragment") - 1 ))
find . -type f -size "+${size}c" -print0 | 
  perl -MSys::Mmap -l -0sne '
    BEGIN {
      open N, "<", $needle or die "$ARGV[0]: $!\n";
      mmap($n, 0, PROT_READ, MAP_SHARED, N);
    }
    if (open H, "<", $_) {
      mmap($h, 0, PROT_READ, MAP_SHARED, H);
      print if index($h, $n) >=0;
    } else {
      warn "$_: $!\n";
    }' -- -needle="$fragment"

答案4

如果您怀疑一个文件是另一个文件的第一部分,您可以从两个文件中获取前几个字节并进行比较:

# Omit or change the bytes arguments as needed, see `man head`
head --bytes=1032 file1.bin > /tmp/file1.head.bin
head --bytes=1032 file2.bin > /tmp/file2.head.bin
diff --text /tmp/file.head.*

您还可以使用 直观地查看文件xxd /tmp/fil1.head.bin。最后,像 Meld 或 Beyond Compare 这样的程序可以向您展示文件的视觉并排比较。

相关内容