【发布时间】:2010-11-28 05:51:12
【问题描述】:
在 Linux 桌面 (RHEL4) 上,我想从一个大文件 (>1 Gig) 中提取一系列字节(通常小于 1000)。我知道文件的偏移量和块的大小。
我可以编写代码来执行此操作,但有命令行解决方案吗?
理想情况下,类似于:
magicprogram --offset 102567 --size 253 < input.binary > output.binary
【问题讨论】:
在 Linux 桌面 (RHEL4) 上,我想从一个大文件 (>1 Gig) 中提取一系列字节(通常小于 1000)。我知道文件的偏移量和块的大小。
我可以编写代码来执行此操作,但有命令行解决方案吗?
理想情况下,类似于:
magicprogram --offset 102567 --size 253 < input.binary > output.binary
【问题讨论】:
我遇到了同样的问题,试图剪切部分 RAW 磁盘映像。 bs=1 的 dd 不可用,因此我为该任务编写了一个简单的 C 程序。
// usage:
// ./cutfile srcfile destfile offset length
// ./cutfile my.image movie.avi 4524 20412452
// compile, presuming it is saved as cutfile.cc:
// gcc cutfile.cc -o cutfile -std=c11 -pedantic -W -Wall -Werror
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int argc, char *argv[])
{
if(argc != 5) {
printf("error, need 4 arguments!\n");
return 1;
}
const unsigned blocksize = 16*512; // can adjust
unsigned char buffer[blocksize];
FILE *f = fopen(argv[1], "rb");
FILE *fout = fopen(argv[2], "wb");
long offset = atol(argv[3]);
long length = atol(argv[4]);
if(f==NULL || fout==NULL) {
perror("cannot open file");
return 1;
}
fseek(f, offset, SEEK_SET);
while(length > blocksize) {
fread(buffer, 1, blocksize, f);
fwrite(buffer, 1, blocksize, fout);
length -= blocksize;
}
if(length>0) { // copy rest
fread(buffer, 1, length, f);
fwrite(buffer, 1, length, fout);
}
fclose(fout);
fclose(f);
return 0;
}
【讨论】:
std::ifstream 和 std::ofstream...
head -c + tail -c
不确定它与dd 在效率方面的对比如何,但它很有趣:
printf "123456789" | tail -c+2 | head -c3
选择 3 个字节,从第 2 个字节开始:
234
另见:
【讨论】:
printf '\x01\x02' > f 和hd。
这是一个老问题,但我想添加另一个更适合大块字节的 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 字节,当要提取的字节数很大时,这会非常慢。
这意味着我们将块大小 (bs) 保留为默认值 512 字节。使用iflag=skip_bytes,count_bytes,我们告诉dd 将skip 和count 之后的值视为字节数量而不是块数量。
【讨论】:
iflag 是一个未知的操作数,没有它你会得到一个完整的块。
dd 可用于支持iflag (brew install coreutils)。注意:默认情况下,安装实用程序时使用 g 前缀(例如 gdd 而不是 dd)
试试dd:
dd skip=102567 count=253 if=input.binary of=output.binary bs=1
选项bs=1 设置块大小,使dd 一次读取和写入一个字节。默认块大小为 512 字节。
bs 的值也会影响skip 和count 的行为,因为skip 和count 中的数字是dd 将跳过的块数和读/写。
【讨论】:
status=none 以禁止输出到stderr。
dd if=in.bin bs=1 status=none skip=$((0x88)) count=$((0x80)) of=out.bin.
更快
dd bs=<req len> count=1 skip=<req offset> if=input.binary of=output.binary
【讨论】:
skip是以bs为单位的。
req_offset=$(bc <<< "$offset/$bs") 并确保它是一个整数。
dd 命令可以完成所有这些。查看作为调用的一部分的 seek 和/或 skip 参数。
【讨论】: