2009-08-13 18 views
11

我試圖將一個塊從一個二進制文件複製到一個新文件中。我有我想要抓取的塊的字節偏移量和長度。如何從unix/linux上的文件抓取任意塊

我已經嘗試使用dd實用程序,但這似乎讀取和放棄直到偏移量的數據,而不只是尋找(我猜是因爲dd是用於複製/轉換數據塊)。這使得它很慢(速度較慢越高offset這是我試過的命令:

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

我想我可以寫一個小的Perl/Python的/任何腳本來打開該文件,尋求偏移,然後讀取和寫入塊所需的數據量。

有沒有支持這樣的一個工具?

+0

我只是試圖運行'對於DD strace',它使用llseek。 – Hasturkun 2009-08-13 16:10:50

+0

這將是GNU dd,順便說一句。 – Hasturkun 2009-08-13 16:23:39

+1

啊,我在freebsd上,所以也許這是一個不同的實現。也許它很慢,因爲我將輸入緩衝區大小設置爲1個字節。 – kevinm 2009-08-13 16:36:59

回答

10

是的,今天用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" 
+0

是的,添加跳過/ count_bytes將是非常有用的,並使dd一個易於使用的通用字節抓取器:) – kevinm 2009-08-18 16:04:21

12

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

1

感謝您的其他答案。不幸的是,我無法安裝額外的軟件,因此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 
+0

緩衝區大小應該足夠大,以保持系統調用(和上下文切換)的數量減少,並且頁面大小的倍數可以使緩存儘可能快樂。內核預讀意味着它不會對請求的磁盤I/O的大小產生任何實際影響。 100000不是4kiB的倍數,但從64kiB到1MiB的值是合理的。 – hobbs 2009-08-14 11:06:54

1

根據mandd on FreeBSD

skip=Ñ

從複製之前的輸入的開始跳過Ñ塊。 在支持搜索的輸入上,使用lseek(2)操作。 否則,輸入數據被讀取並丟棄。對於管道,將讀取正確的字節數 。對於所有其他設備,將讀取正確數量的塊,而不區分 正在讀取的部分或完整塊。

使用dtruss我驗證了它在Mac OS X上的輸入文件中使用如果你認爲速度很慢,那麼我同意評論這是由於1字節的塊大小。

0

您可以嘗試hexdump都命令:

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

例)讀取 'mycorefile' 100個字節偏移從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\[email protected]\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 |[email protected]| 
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 
#