高效使用 dd(缓冲多个块,一次处理一个)

高效使用 dd(缓冲多个块,一次处理一个)

$templateBlock给定一个文件,我需要搜索与特定大小的输入块匹配的块数$blockSize

dd完成这项任务的有效方法是什么?下面的方法很糟糕而且很慢,因为它调用了dd太多次。

while [ $i -lt $totalBlocks]; do
  dd if="$pathToFile" bs=$blockSize count=1 skip=$i | diff $templateBlock -
  # Increase $count if $? is 0
  # Increase $i by 1 
done

最好的方法可能是dd阅读$totalSize,并且$blockSize一次只处理所有阅读的内容。这样,我只需要调用dd一次。换句话说,dd一次读取所有(或许多)块,并且我可以一次处理每个块。是否有可能做到这一点?

也许是这样的:

dd if="$pathToFile" bs=$blockSize | for-each-block {
  diff $templateBlock -
  # Update $count if $? is 0
}

理想情况下,我只想使用 shell 实用程序。
换句话说,我宁愿不必使用 Python 或类似的程序编写程序。

答案1

在 shell 脚本中,最好使用cmpGNU diffutils。它会为您比较数据,甚至可以跳过偏移量,--ignore-initial=SKIP1:SKIP2以便您可以针对每个扇区偏移量运行,并且它将在找到的第一个差异处退出......这是半高效的,但如果您想运行,cmp这仍然是很多调用cmp它对于每个部门...

您还可以使用grep -abostrings -t d来查找可能的字节偏移候选,但这取决于您正在寻找的实际模式。这样做的优点是一次程序调用即可搜索整个内容,而不是数千次调用(每个扇区一次)。

除非您碰巧找到一个恰好可以为您完成所有工作的命令行实用程序,否则您无法击败根据您的要求一次性搜索整个内容的小型 C/Go/Python 脚本...

您的脚本想法当然也有效,但它只是意味着在循环内再次调用dd(或,或其他)以一次读取一个标准输入块,它可能比以前慢......read

答案2

您可以使用该split命令对文件的连续块运行“过滤器”,并使用cmpecho和编写过滤器true,为每个成功的匹配获取换行符,然后用于wc对这些匹配进行计数。例如,如果$F是文件、$TB模板块文件和$SZ模板块的大小,则它可能类似于以下命令行:

$ split -b $SZ --filter="cmp $TB >& /dev/null && echo ; true" $F | wc -l

请注意,true这可确保过滤器命令行成功,并且为了节省输入,您可以使用它:来代替,尽管这不会提高可读性。

还要注意所有输出的重定向cmp,即它的 stdout 和 stderr,因为只有它的返回代码是感兴趣的。

相关内容