我有一张 64GB 的 MicroSD 卡。我向其中写入了一个大小为 16GB 的图像:
$ sudo dd if=my_image.img of=/dev/sdb bs=4M
3798+1 records in
3798+1 records out
15931539456 bytes (16 GB, 15 GiB) copied, 657.848 s, 24.2 MB/s
现在,我想使用 dd 拍摄同一张 64GB SD 卡的前 15931539456 字节 (16GB) 的图像,最终得到一个与我开始使用的图像具有相同校验和的图像。
据我了解,上面 dd 的结果(3798+1)表明,从源图像中有 3798 个完整读取,以及 1 个部分读取,因为源图像的大小没有均匀地分割成 4M 块。那么我如何告诉 dd 现在将 15931539456 字节从 SD 卡复制到一个新文件中,一次 4M?
我假设我可以做类似的事情:
sudo dd if=/dev/sdb of=new_image.img bs=1 count=15931539456
但缓冲区这么小会使操作永远持续下去。有没有办法告诉它使用 4M 的缓冲区,但只复制 X 个字节,即使这会导致最后的读取很短?
答案1
几种可能性:
使用更小的
bs
,但不是很小:dd if=/dev/sdb of=new_image.img bs=512k count=30387
这不是一个通用的解决方案。它在这里起作用是因为
15931539456
可以因式分解。使用您想要的
bs
,阅读更多内容并即时截断:dd if=/dev/sdb bs=4M | head -c 15931539456 >new_image.img
你不需要
count=3799
这里。好吧,你甚至不需要dd
:head -c 15931539456 /dev/sdb >new_image.img
我希望
head
能够阅读理智的内容并表现良好。head -c
POSIX 不需要注释。使用您想要的
bs
,阅读更多内容并稍后截断:dd if=/dev/sdb of=new_image.img bs=4M count=3799 truncate -s 15931539456 new_image.img
truncate
虽然不便于携带。用你所想
bs
,少读书;然后阅读剩余部分bs=1
:dd if=/dev/sdb of=new_image.img bs=4M count=3798 offset=$((3798*4*1024*1024)) remaining=$((15931539456-offset)) dd if=/dev/sdb of=new_image.img bs=1 skip="$offset" seek="$offset" count="$remaining"
注意一般情况下dd
可能会读取部分块,这仍然会增加计数(比较这个答案)。当从块设备读取时,这可能不会发生,但通用的解决方案仍然是iflag=fullblock
每当您依赖count
且bs
大于时始终指定1
。不幸的fullblock
是 POSIX 并不要求,您dd
可能支持也可能不支持。