如何从Unix/Linux上的文件中抓取任意块[duplicate]

pkwftd7m  于 2022-12-29  发布在  Unix
关注(0)|答案(6)|浏览(160)
    • 此问题在此处已有答案**:

How do I extract a single chunk of bytes from within a file?(6个答案)
5年前关闭。
我试图从一个二进制文件中复制一个块到一个新文件中。我有我想抓取的块的字节偏移量和长度。
我试过使用dd实用程序,但这似乎读取并丢弃了偏移量之前的数据,而不是仅仅查找(我猜是因为dd用于复制/转换数据块)。这使得它相当慢(偏移量越大,速度越慢)。

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

我想我可以编写一个小的Perl/Python/whatever脚本来打开文件,查找偏移量,然后以块的形式读写所需数量的数据。
是否有实用程序支持这样的功能?

vulvrdjw

vulvrdjw1#

您可以使用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

啊,没看到它必须寻找。留下这个作为社区维基。

wfauudbj

wfauudbj2#

是的,现在用dd做这个很难。我们考虑在coreutils中给dd添加skip_bytes和count_bytes参数,不过下面的应该可以:

#!/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"
f2uvfpb9

f2uvfpb93#

谢谢你的回答。不幸的是,我没有能力安装额外的软件,所以ddrescue选项被取消了。head/tail解决方案很有趣(我不知道你可以提供+到tail),但是扫描数据会让它很慢。
我最后写了一个小的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
w8ntj3qf

w8ntj3qf4#

您可以使用

--input-position=POS

ddrescue的选项。

zlhcx6iw

zlhcx6iw5#

根据mandd on FreeBSD
skip= * n *
复制前跳过输入开头的 * n * 个块。**在支持寻道的输入上,使用lseek(2)操作。**否则,读取并丢弃输入数据。对于管道,读取正确的字节数。对于所有其他设备,读取正确的块数,而不区分正在读取的是部分块还是完整块。
使用dtruss,我验证了它确实在Mac OS X上的输入文件上使用lseek()。如果你只是认为它很慢,那么我同意评论,这将是由于1字节的块大小。

50pmv0ei

50pmv0ei6#

您可以尝试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
#

相关问题