如何从unix / linux上的文件抓取任意块

我试图从一个二进制文件复制一个块到一个新的文件。 我有我想抓取的块的字节偏移量和长度。

我已经尝试使用dd工具,但这似乎读取和丢弃数据的偏移量,而不是只是寻求(我猜是因为dd是为了复制/转换数据块)。 这使得它非常慢(偏移越高,速度越慢)。这是我试过的命令:

 dd if=inputfile ibs=1 skip=$offset count=$datalength of=outputfile 

我想我可以写一个小的perl / python /任何脚本来打开文件,寻找偏移量,然后读取和写入所需数量的数据块。

有没有支持这样的东西的实用程序?

是的,今天用dd来做这件事很尴尬。 我们正在考虑在coreutils中将skip_bytes和count_bytes参数添加到dd来提供帮助。 以下应该工作:

 #!/bin/sh bs=100000 infile=$1 skip=$2 length=$3 ( dd bs=1 skip=$skip count=0 dd bs=$bs count=$(($length / $bs)) dd bs=$(($length % $bs)) count=1 ) < "$infile" 

您可以使用tail -c+N修剪输入中的前N个字节,然后可以使用head -cM仅输出其输入中的前M个字节。

 $ echo "hello world 1234567890" | tail -c+9 | head -c6 rld 12 

所以使用你的变量,可能是:

 tail -c+$offset inputfile | head -c$datalength > outputfile 

啊,没有看到它必须寻求。 离开这个CW。

感谢其他答案。 不幸的是,我不能安装额外的软件,所以ddrescue选项已经不存在了。 头部/尾部解决方案很有趣(我没有意识到你可以提供+尾巴),但通过数据扫描使得它非常缓慢。

我最终写了一个小python脚本来做我想要的。 缓冲区大小可能应该被调整为与某些外部缓冲区设置相同,但使用下面的值在我的系统上已经足够高性能了。

 #!/usr/local/bin/python import sys BUFFER_SIZE = 100000 # Read args if len(sys.argv) < 4: print >> sys.stderr, "Usage: %s input_file start_pos length" % (sys.argv[0],) sys.exit(1) input_filename = sys.argv[1] start_pos = int(sys.argv[2]) length = int(sys.argv[3]) # Open file and seek to start pos input = open(sys.argv[1]) input.seek(start_pos) # Read and write data in chunks while length > 0: # Read data buffer = input.read(min(BUFFER_SIZE, length)) amount_read = len(buffer) # Check for EOF if not amount_read: print >> sys.stderr, "Reached EOF, exiting..." sys.exit(1) # Write data sys.stdout.write(buffer) length -= amount_read 

根据FreeBSD上的man dd

skip= n

在复制之前从输入的开头跳过n个块。 在支持搜索的输入上,使用lseek(2)操作。 否则,输入数据被读取并丢弃。 对于管道,将读取正确的字节数。 对于所有其他设备,读取正确数量的块,而不区分正在读取的部分块或完整块。

使用dtruss我验证了它确实在Mac OS X上的输入文件上使用了lseek() 。如果你认为速度很慢,那么我同意这是由于1字节的块大小造成的。

你可以使用

 --input-position=POS 

ddrescue的选项。

你可以试试hexdump命令:

  hexdump -v <File Path> -c -n <No of bytes to read> -s <Start Offset> | awk '{$1=""; print $0}' | sed 's/ //g' 

例如)从偏移量100开始,从“mycorefile”中读取100个字节。

 # hexdump -v -c mycorefile -n 100 -s 100 | awk '{$1=""; print $0}' | sed 's/ //g' \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0001\0\0\0005\0\0\0\0020003\0 \0\0\0\0\0\0@\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0 003\0 \0\0\0\0\0020\0\0\0\0\0\0001\0\0\0 006\0\0\0\0020003\0\0\0\0\0\0220c\0 \0\0\0\0 

然后,如果需要,使用另一个脚本将输出的所有行连接到单行。

如果你只是想看到的内容:

 # /usr/bin/hexdump -v -C mycorefile -n 100 -s 100 00000064 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000074 00 00 00 00 01 00 00 00 05 00 00 00 00 10 03 00 |................| 00000084 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........| 00000094 00 00 00 00 00 00 00 00 00 00 00 00 00 a0 03 00 |................| 000000a4 00 00 00 00 00 10 00 00 00 00 00 00 01 00 00 00 |................| 000000b4 06 00 00 00 00 10 03 00 00 00 00 00 00 90 63 00 |..............c.| 000000c4 00 00 00 00 |....| 000000c8 #