it-swarm-id.com

Cara terbaik untuk menghapus byte dari awal file?

Hari ini saya harus menghapus 1131 byte pertama dari file campuran teks/biner 800MB, sebuah tempat sampah Subversion yang disaring. Saya meretas untuk repositori baru. Apa cara terbaik untuk melakukan ini?

Untuk mulai dengan saya mencoba

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

tetapi setelah melewatkan salinan ini sisa file byte pada suatu waktu, yaitu sangat lambat. Pada akhirnya saya berhasil saya perlu 405 byte untuk membulatkan ini hingga tiga blok dari 512 yang bisa saya lewati

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

yang selesai cukup cepat tetapi pasti ada cara yang lebih sederhana/lebih baik? Apakah ada alat lain yang saya lupa? Terima kasih!

64
Rup

Anda dapat beralih bs dan melewati opsi:

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

Dengan cara ini operasi dapat mengambil manfaat dari blok yang lebih besar.

Jika tidak, Anda bisa mencoba dengan tail (meskipun tidak aman untuk menggunakannya dengan file biner):

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

Akhirnya, Anda dapat menggunakan instance 3 dd untuk menulis sesuatu seperti ini:

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

di mana dd pertama mencetak output standarnya difilter.dump; yang kedua hanya membaca 1131 byte dan membuangnya; kemudian, yang terakhir membaca dari input standar byte yang tersisa dari filtered.dump dan menuliskannya ke trimmed.dump.

67
marco

Tidak yakin kapan skip_bytes telah ditambahkan, tetapi untuk melewati 11 byte pertama yang Anda miliki:

# 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

Dimana iflag=skip_bytes memberitahu dd untuk menginterpretasikan nilai untuk opsi skip sebagai byte alih-alih blok, membuatnya langsung.

Anda dapat menggunakan sub-Shell dan dua dd panggilan seperti ini:

$ ( 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

Jika filesystem dan kernel Linux mendukungnya maka Anda dapat mencoba fallocate jika Anda ingin membuat perubahan di tempat: dalam kasus terbaik tidak ada data IO sama sekali:

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

dimana <magic> tergantung pada sistem file, versi Linux, dan jenis file ( FALLOC_FL_COLLAPSE_RANGE atau FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE dapat digunakan secara internal ).

7
jfs

Anda harus menggunakan count=0 - itu adalah lseek() sederhana bila memungkinkan.

Seperti ini:

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

dd akan lseek() deskriptor file input ke offset 1131 byte, dan kemudian cat hanya akan menyalin apa pun yang tersisa ke output.

3
mikeserv

Namun cara lain untuk menghapus byte utama dari file (tanpa menggunakan dd sama sekali) adalah dengan menggunakan xxd dan sed atau tail masing-masing.

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 meminta liner online. Inilah satu di Perl. Dibutuhkan 2 argumen: Dari byte dan panjang. File input harus diberikan oleh '<' dan output akan berada di 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

Jika panjangnya lebih besar dari file, sisa file akan disalin.

Di sistem saya ini memberikan 3,5 GB/s.

2
Ole Tange