我有数据恢复软件生成的图像文件的片段。我怀疑完整的原件位于我的家庭文件服务器上的某个地方。
如果这是文本文件的片段,我可以抓取一个看起来独特的片段,运行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
使用perl
Sys::Mmap 模块(在libsys-mmap-perl
Debian 上的包中):
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 这样的程序可以向您展示文件的视觉并排比较。