使用dd命令跳过stdin的前32k字节?

7
如果我在文件系统上有一个文件,我可以使用dd命令执行以下操作:
dd  if=/my/filewithaheader.bin bs=32k skip=1 | gunzip | tar tvf

然而,如果我尝试像这样做:

./commandthatputsstuffonstdout |  dd  bs=32k skip=1 | gunzip | tar tvf

我遇到了这个错误: dd: 'standard input': cannot skip to specified offset
我该如何解决,能否使用dd修复,还是有其他的Unix命令可以使用呢?
3个回答

6
您可以使用tail命令。例如:
./commandthatputsstuffonstdout | tail -c +1025 ...

要跳过命令产生的前 1024 个字节输出。

摘自 tail 手册

   -c, --bytes=K
          output the last K bytes; alternatively,  use  -c  +K  to  output
          bytes starting with the Kth of each file

2
哦,多么丑陋的语义。要跳过1024个字节,给出+1024会更合乎逻辑。但是不,他们选择了另外一种方式 :-( - glglgl

4

我也遇到了这个问题,使用fullblock iflag可以防止短读取和随后的中止。

例如:

gzip -d < ./disk_image.dd.gz | \
    dd bs=4M skip=32768 iflag=fullblock,skip_bytes of=./partial_image.dd

skip_bytes只有在你想要使用字节而不是bs作为skip时才是必需的,因此与问题无关据我所知。 - doak

0

回答有点晚,但这个 dd 示例对我很有效。

创建示例源文件:

$ dd if=/tmp/somefile of=/tmp/test skip=50 bs=100 count=1

跳过50个字节,将其后的10个字节复制到test_skip文件中:

$ dd if=/tmp/test of=/tmp/test_skip skip=50 bs=1 count=10
10+0 records in
10+0 records out
10 bytes (10 B) copied, 8.2091e-05 s, 122 kB/s

或从标准输入读取数据:

cat /tmp/test| dd of=/tmp/stdin bs=1 skip=50 count=1

验证输出:

$ hexdump /tmp/test
0000000 ebf3 e8fd df1b 0aa1 faa3 1fba 1817 1267
0000010 1402 f539 fb69 f263 f319 084b 0b26 1150
0000020 182a f98d 030c e0b0 e47c f13d ef3b 1146
0000030 0b7e 0f72 0e58 f2bd f403 ee95 e529 0567
0000040 f88e 1994 0e83 12e5 11e7 fd4b 032f f4f0
0000050 fc9d 010a 0ab6 06b6 1224 f5cb 01e4 e67a
0000060 ebe0 f1a0                              
0000064

$ hexdump /tmp/test_skip
0000000 0f72 0e58 f2bd f403 ee95

源文件偏移量50是字节:0x0f


1
请注意,该问题涉及跳过来自标准输入(stdin)的数据,而不是文件;因此,这并不能回答该问题。 - nwaltham
非常正确,dd也可以与stdin一起使用。$ cat /tmp/test| dd of=/tmp/stdin bs=1 skip=50 count=10 - henpel
1
是的 - 但你有尝试使用skip吗?看一下问题。当我像那样尝试时,我得到了一个错误dd:'standard input':无法跳转到指定的偏移量;这就是我在这里提出问题的原因。说实话,2013年已经在这里收到的答案解决了我的问题,并且我接受了答案。我只是给你一些提示,以帮助你未来在SE上的交互,否则你可能会得到负面的回答。 - nwaltham
谢谢您的提示。我试着重复了您的尝试,像这样:dd if=/dev/zero of=/tmp/zeros bs=1 count=32k echo "teststrings" >> /tmp/zeros cat /tmp/zeros| dd of=/tmp/test_3 bs=1 count=11 skip=32k cat /tmp/test_3 teststrings[henpel@~]$ - henpel
1
dd if=/dev/zero of=/tmp/zeros bs=1 count=32k; echo "teststrings" >> /tmp/zeros; cat /tmp/zeros| dd of=/tmp/test_3 bs=1 count=11 skip=32k; cat /tmp/test_3;将上述程序相关内容翻译成中文。仅返回翻译后的文本。 - henpel
你的方法可能有效是因为你使用了 bs=1,但是对于其他块大小(例如:bs=4M)可能不起作用... bs=1 的效率非常低下,会使处理大型数据集变得非常缓慢。请查看我的答案以获取更合适的方法。 - Attie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接