it-swarm-ko.tech

파일 시작 부분에서 바이트를 제거하는 가장 좋은 방법은 무엇입니까?

오늘은 800MB 혼합 텍스트/이진 파일에서 첫 번째 1131 바이트를 제거해야했습니다. 여기서 새로운 저장소를 위해 해킹중인 필터링 된 Subversion 덤프입니다. 가장 좋은 방법은 무엇입니까?

나는 시도했다

dd bs=1 skip=1131 if=filtered.dump of=trimmed.dump

그러나 건너 뛰기 후에는 파일의 나머지 부분이 한 번에 한 바이트 씩, 매우 느리게 복사됩니다. 결국 나는 이것을 건너 뛸 수있는 512의 3 블록으로 반올림하기 위해 405 바이트가 필요했습니다.

dd if=/dev/zero of=405zeros bs=1 count=405
cat 405zeros filtered.dump | dd bs=512 skip=3 of=trimmed.dump

어느 것이 상당히 빨리 완료되었지만 더 간단하고 더 나은 방법이 있었습니까? 잊어 버린 다른 도구가 있습니까? 감사!

64
Rup

Bs를 전환하고 옵션을 건너 뛸 수 있습니다.

dd bs=1131 skip=1 if=filtered.dump of=trimmed.dump

이런 식으로 작업은 더 큰 블록의 이점을 얻을 수 있습니다.

그렇지 않으면 tail로 시도 할 수 있습니다 (이진 파일과 함께 사용하는 것이 안전하지는 않지만).

tail -c +1132 filtered.dump >trimmed.dump

마지막으로 3 dd 인스턴스를 사용하여 다음과 같이 작성할 수 있습니다.

dd if=filtered.dump bs=512k | { dd bs=1131 count=1 of=/dev/null; dd bs=512k of=trimmed.dump; }

여기서 첫 번째 dd는 표준 출력을 필터링합니다. 두 번째는 1131 바이트를 읽고 버립니다. 그런 다음 마지막 입력은 표준 입력에서 남아있는 bytes.filter.dump를 읽고 trimmed.dump에 씁니다.

67
marco

skip_bytes이 (가) 추가되었지만 처음 11 바이트를 건너 뛰려면 다음을 수행하십시오.

# echo {123456789}-abcdefgh- | 
                              dd bs=4096 skip=11 iflag=skip_bytes
-abcdefgh-
0+1 records in
0+1 records out
11 bytes (11 B) copied, 6.963e-05 s, 158 kB/s

어디 iflag=skip_bytes는 dd에게 skip 옵션의 값을 블록 대신 바이트로 해석하도록 지시하여 간단하게 만듭니다.

다음과 같이 하위 쉘과 두 개의 dd 호출을 사용할 수 있습니다.

$ ( dd bs=1131 count=1 of=dev_null && dd bs=4K of=out.mp3 ) < 100827_MR029_LobbyControl.mp3
1+0 records in
1+0 records out
1131 bytes (1.1 kB) copied, 7.9691e-05 s, 14.2 MB/s
22433+1 records in
22433+1 records out
91886130 bytes (92 MB) copied, 0.329823 s, 279 MB/s
$ ls -l *
-rw------- 1 max users 91887261 2011-02-03 22:59 100827_MR029_LobbyControl.mp3
-rw-r--r-- 1 max users     1131 2011-02-03 23:04 dev_null
-rw-r--r-- 1 max users 91886130 2011-02-03 23:04 out.mp3
$ cat dev_null out.mp3 > orig
$ cmp 100827_MR029_LobbyControl.mp3 orig
15
maxschlepzig

파일 시스템과 Linux 커널이이를 지원하는 경우 변경을 수행하려는 경우 fallocate 을 시도 할 수 있습니다. 최상의 경우에는 데이터가 없습니다 IO 전혀 :

$ fallocate <magic> -o 0 -l 1131 inplace.dump

어디 <magic>는 파일 시스템, Linux 버전 및 파일 유형 ( FALLOC_FL_COLLAPSE_RANGE 또는 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE는 내부적으로 사용할 수 있음 ).

7
jfs

count=0를 사용해야합니다. 가능할 때마다 간단한 lseek()입니다.

이처럼 :

{  dd bs=1131 skip=1 count=0; cat; } <filtered.dump >trimmed.dump

dd는 입력 파일 디스크립터를 1131 바이트 오프셋으로 lseek()하고 cat은 출력에 남은 모든 것을 간단히 복사합니다.

3
mikeserv

파일에서 선행 바이트를 제거하는 또 다른 방법 (dd을 전혀 사용하지 않음)은 각각 xxdsed 또는 tail를 사용하는 것입니다.

bytes=$((1131*2))

xxd -p -c 256 filtered.dump | tr -d '\n' | sed "s/^.\{0,${bytes}\}//" | xxd -r -p > trimmed.dump

bytes=$((bytes + 1)) 
xxd -p -c 256 filtered.dump | tr -d '\n' | tail -c +${bytes} | xxd -r -p > trimmed.dump
2
wop

@maxschlepzig는 온라인 라이너를 요청합니다. 여기 Perl에 있습니다. 바이트와 ​​길이에서 2 개의 인수가 필요합니다. 입력 파일은 '<'로 제공되어야하며 출력은 stdout에 있습니다.

Perl -e 'sysseek(STDIN,shift,0) || die; $left = shift;
     while($read = sysread(STDIN,$buf, ($left > 32768 ? 32768 : $left))){
        $left -= $read; syswrite(STDOUT,$buf);
     }' 12345678901 19876543212 < bigfile > outfile

길이가 파일보다 크면 나머지 파일이 복사됩니다.

내 시스템에서 이것은 3.5GB/s를 제공합니다.

2
Ole Tange