如何使用 dd 用“FF”填充文件?

如何使用 dd 用“FF”填充文件?

如何0xFF使用填充文件dd

此命令将用零填充输出文件,直到文件大小达到 100 KB:

dd if=inputFile.bin ibs=1k count=100 of=paddedFile.bin conv=sync

0xFF但是,我想用s 而不是s来填充文件0x00

答案1

据我所知,您无法指示dd填充文件。但您可以指示dd写入预先填充的文件。

首先创建一个所需大小的文件,内容如下0xFF

$ dd if=/dev/zero ibs=1 count=102400 | LC_ALL=C tr "\000" "\377" >paddedFile.bin
100+0 records in
200+0 records out
102400 bytes (102 kB) copied, 0,0114595 s, 8,9 MB/s

或者你可以使用head

$ head -c 102400 /dev/zero | LC_ALL=C tr "\000" "\377" >paddedFile.bin

结果:

$ hexdump -C paddedFile.bin 
00000000  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*
00019000

然后将输入文件插入“填充”文件的开头:

$ dd if=inputFile.bin of=paddedFile.bin conv=notrunc
0+1 records in
0+1 records out
8 bytes (8 B) copied, 7,4311e-05 s, 108 kB/s

输入文件示例:

$ hexdump -C inputFile.bin 
00000000  66 6f 6f 0a 62 61 72 0a                           |foo.bar.|
00000008

结果:

$ hexdump -C paddedFile.bin 
00000000  66 6f 6f 0a 62 61 72 0a  ff ff ff ff ff ff ff ff  |foo.bar.........|
00000010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*
00019000

解释

$ dd if=inputFile.bin of=paddedFile.bin conv=notrunc
                                        ^^^^^^^^^^^^

conv=notrunc告诉dd不要截断输出文件。

$ dd if=/dev/zero ibs=1 count=102400 | LC_ALL=C tr "\000" "\377" >paddedFile.bin
                                                          ^^^^^^

tr期望参数为八进制。\377是八进制的0xFF

$ dd if=/dev/zero ibs=1 count=102400 | LC_ALL=C tr "\000" "\377" >paddedFile.bin
                                       ^^^^^^^^

tr可以依赖于语言环境,因此为了安全起见,请将语言环境设置为C

$ dd if=/dev/zero ibs=1 count=102400 | LC_ALL=C tr "\000" "\377" >paddedFile.bin
                  ^^^^^

dd如果不能足够快地读取一个满是字节的块,则可能会写出较少的字节。要确定大小,您需要将块大小设置为 1。head没有这个问题。

请点击此处了解更多信息:https://unix.stackexchange.com/questions/278443/whats-the-posix-way-to-read-an-exact-number-of-bytes-from-a-file

答案2

lesmana 的答案的一个可能的改进是就地对文件进行操作。对于大型输入文件来说,这可能会快得多,并且还会使稀疏文件保持稀疏。但是,在许多情况下,您不想修改输入文件,因此这种方法不合适。

以下示例从一个大型稀疏输入文件开始,并用 FF 字符将其填充到 1GB 大小。只需更改newsize为所需的值即可。如您所见,dd尽管这个文件非常大,但该部分仅花费几分之一秒的时间。

$ ls -ld inputFile.bin
-rw-rw-r-- 1   …   1073741700   …   inputFile.bin
$ hexdump inputFile.bin
0000000 0000 0000 0000 0000 0000 0000 0000 0000
*
3fffff80 0000 0000
3fffff84

$ newsize=$((1024 * 1024 * 1024))
$ filesize=$(stat -c "%s" inputFile.bin)
$ padcount=$((newsize - filesize))
$ dd if=/dev/zero ibs=1 count="$padcount" | tr "\000" "\377" >> inputFile.bin
124+0 records in
0+1 records out
124 bytes (124 B) copied, 0.000162309 s, 764 kB/s

$ ls -ld inputFile.bin
-rw-rw-r-- 1   …   1073741824   …   inputFile.bin
$ hexdump inputFile.bin
0000000 0000 0000 0000 0000 0000 0000 0000 0000
*
3fffff80 0000 0000 ffff ffff ffff ffff ffff ffff
3fffff90 ffff ffff ffff ffff ffff ffff ffff ffff
*
40000000

答案3

tl;dr:转到最后一个代码块,就在粗体文本下方,上面写着“这是我在 Debian 12 中将使用的完整命令”。


使用单个管道就可以做到这一点。

将输入文件和字节源的输出连接起来0xFF,然后仅dd在 100 KiB 之后停止写入输出文件。这可以通过两种方式完成:

# flawed, keep reading
{ cat inputFile.bin && </dev/zero LC_ALL=C tr '\000' '\377'; } | dd ibs=1k count=100 of=paddedFile.bin
# flawed, keep reading 
</dev/zero LC_ALL=C tr '\000' '\377' | cat inputFile.bin - | dd ibs=1k count=100 of=paddedFile.bin

我发现第一种语法更好,因为从左到右阅读时,它可以正确显示数据流:
inputFile.bin+ whattr打印paddedFile.bin所需大小的 →。
第二种语法从 开始tr,因此在这方面不太优雅。

这两个命令都有缺陷,因为dd可能会读得更少,ibs但仍然增加计数第一个命令最有可能遭受此种损失,第二个命令可能很幸运,不会偶然遭受损失;但两个命令仍可能遭受损失。解决这个问题的唯一 POSIX 方法是使用ibs=1

# OK, portable
… | dd ibs=1 count=102400 of=paddedFile.bin

其中表示dd来自第一个或第二个有缺陷的命令的管道的预片段(现在两者都可以正常工作,缺陷来自dd)。

如果您dd支持iflag=fullblock那么这将是可以的(但不是 POSIX):

# OK, not portable
… | dd ibs=1k count=100 of=paddedFile.bin iflag=fullblock

或者如果你的head支持-c(也不是 POSIX)那么你可以使用headdd

# OK, not portable
… | head -c 102400 > paddedFile.bin

head甚至可能支持-c 100K这是我在 Debian 12 中使用的完整命令:

# OK, not portable, quite elegant
{ cat inputFile.bin && </dev/zero LC_ALL=C tr '\000' '\377'; } | head -c 100K > paddedFile.bin

请注意,此答案中任何无缺陷的命令都会产生paddedFile.bin恰好 100 KiB 的大小(除非发生类似这样的致命错误)。即使大于 100 KiB,access denied也是如此。inputFile.bin

相关内容