如何从文件中提取单个字节块?


79

在Linux桌面(RHEL4)上,我想从大文件(> 1 Gig)中提取一定范围的字节(通常小于1000)。我知道文件的偏移量和块的大小。

我可以编写代码来执行此操作,但是有命令行解决方案吗?

理想的情况是:

magicprogram --offset 102567 --size 253 < input.binary > output.binary

Answers:


117

尝试dd

dd skip=102567 count=253 if=input.binary of=output.binary bs=1

2
(可选)添加status=none以禁止输出到stderr。
kenorb 2015年

13
这是使用十六进制偏移量的示例:dd if=in.bin bs=1 status=none skip=$((0x88)) count=$((0x80)) of=out.bin
kenorb 2015年

@kenorb:我相信十六进制语法是Bash的一部分,因此不一定与其他Shell一起使用。我本人使用tcsh(请不要打我!),您的示例在那里不起作用。
Thomas Padron-McCarthy 2015年

1
有特定的原因为什么您使用bs = 1和count = 253而不是相反?更大的块大小会使命令更有效吗?
rexford

1
@rexford:跳转号也是以块为单位,而不是253的倍数。并且,由于OS在从文件系统上的普通文件读取时会进行自身的缓冲,因此效率不会像从设备读取时。
Thomas Padron-McCarthy

51

这是一个老问题,但是我想添加另一个版本的dd命令,该版本更适合大块字节:

dd if=input.binary of=output.binary skip=$offset count=$bytes iflag=skip_bytes,count_bytes 

其中$offset$bytes是数字,以字节为单位。

与Thomas接受的答案的不同之处在于,bs=1此处没有出现。bs=1产生的输入和输出块大小为1个字节,这在要提取的字节数较大时会非常慢。


4
这确实比我的回答快得多。
Thomas Padron-McCarthy

1
在Mac上不起作用-iflag是未知的操作数,没有它,您将得到整个块。
Timmmm

1
@Timmmm GNUdd可用于iflag支持(brew install coreutils)。注意:默认情况下,实用程序安装时带有g前缀(例如gdd代替dd
Shakil

9

head -c + tail -c

不确定dd效率如何,但是很有趣:

printf "123456789" | tail -c+2 | head -c3

从第二个开始选择3个字节:

234

另请参阅:https : //stackoverflow.com/a/1272995/895245


@ elvis.dukaj是的,应该没有什么不同。尝试使用printf '\x01\x02' > fhd
西罗Santilli郝海东冠状病六四事件法轮功

2
比bs = 1的dd快得多,谢谢!请注意,tail从1开始计数字节,而不是从0开始计数。另外,当head的输出过早关闭时,tail以错误代码1退出。使用“ set -e”时,请确保忽略该错误。
proski

2

dd命令可以完成所有这些操作。在调用中查看seek和/或skip参数。


2

甚至更快

dd bs=<req len> count=1 skip=<req offset> if=input.binary of=output.binary 

2
这里的问题skip是,单位为bs
Arkku

但是,这应该是最受支持的答案,bs = 1的答案是缓慢的:D
Tchakabam

它是执行者的一个细节,并且比上面的要好,您需要像这样重新计算:req_offset=$(bc <<< "$offset/$bs")并确保结果是一个舍入值。
特卡卡姆邦
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.