如何以合理的速度复制二进制文件的任意部分?

如何以合理的速度复制二进制文件的任意部分?

如何以合理的速度复制二进制文件的任意部分?

显然,ddwithbs=1非常慢,而设置bs为另一个值则无法复制任意部分。

这是错的吗?可以用 做吗dd?如果不是的话,那么工具是什么?

例如,这个命令,

dd if="$img" of=tail.bin bs=2147483648 skip=1 status=progress

复制错误的尾部。

这个命令

dd if="$img" of=tail.bin bs=1 skip=2147483648 status=progress

非常慢。

答案1

GNU dd 支持count_bytes, seek_bytes,skip_bytes标志。这允许您使用具有任意偏移和大小的高性能块大小选择。

如果您指定字节单位,GNU dd 自版本 9.1 起默认执行此操作。

引用自coreutils/新闻:

如果块计数以“B”结尾,dd 现在计算字节而不是块。例如,“dd count=100KiB”现在复制 100 KiB 数据,而不是 102,400 个数据块。因此,标志 count_bytes、skip_bytes 和eek_bytes 已过时并且不再记录,尽管它们仍然有效。

另一种选择是创建具有所需偏移和尺寸限制的循环设备。这适用于本身不支持任意偏移的 dd (或任何其他程序)。

或者,您也可以考虑仅复制 bs=1 的部分第一个/最后一个块以及具有所需较大块大小的中间段。

答案2

尝试这个:

tail -c +$FROM file.dat | head -c $LENGTH > file1.dat

只需根据需要分配 FROM 和 LENGTH 即可。请注意, 的编号tail是基于1 的,例如tail -c +4表示从第四个字节开始,即跳过前三个字节。

举个例子:

$ printf 'abcdefghijklmnopqrstuvwxyz\n' > test.txt
$ tail -c +4 test.txt | head -c 6; echo
defghi

答案3

如果您希望文件的整个尾部从某个位置开始,一种方法是寻找文件描述符到正确的位置,然后使用cat.使用 Perl 和 shell 重定向相对简单:

$ printf 'abcdefghijklmnopqrstuvwxyz\n' > test.txt
$ { perl -e 'sysseek STDIN, 23, 0'; cat; } < test.txt
xyz

或者使用通过环境传递的计数,以免与代码混淆:

$ { N=23 perl -e 'sysseek STDIN, $ENV{N}, 0'; cat; } < test.txt
xyz

一个子shell(perl; cat)也可以工作。请注意,这是不是一个管道,只是perlcat使用相同的打开文件描述。尽管请注意上面缺乏错误检查,但如果查找失败,它就不会发生。

要仅复制设定数量的字节,请使用管道 tohead -c而不是cat

$ start=3 count=6
$ { N=$start perl -e 'sysseek STDIN, $ENV{N}, 0'; head -c $count; } < test.txt; echo
defghi

相关内容