Bagaimana cara menghasilkan file dari offset yang ditentukan, tetapi tidak “dd bs = 1 skip = N”?

28

Bagaimana melakukan sesuatu seperti dd if=somefile bs=1 skip=1337 count=31337000, tetapi efisien, tidak menggunakan tidak membaca dan menulis 1-byte?

Solusinya diharapkan:

  1. Sederhananya (untuk non-sederhana saya dapat menulis beberapa Perl oneliner yang akan melakukan ini)
  2. Untuk mendukung offset dan panjang yang besar (jadi peretasan dengan ukuran blok di dd tidak akan membantu)

Solusi parsial (tidak cukup sederhana, mencoba yang sama dengan panjang akan membuatnya lebih kompleks):

dd if=somefile bs=1000 skip=1 count=31337 | { dd bs=337 count=1 of=/dev/null; rest_of_pipeline; }
# 1337 div 1000 and 1337 mod 1000
Vi.
sumber
Apakah Anda mencoba mengubah ukuran blok yang dd gunakan?
cmorse
Blokir yang diubah => unit yang diubah untuk lewati dan hitung
Vi.

Jawaban:

37

Ini harus dilakukan (pada gnu dd):

dd if=somefile bs=4096 skip=1337 count=31337000 iflag=skip_bytes,count_bytes

Jika Anda menggunakan seek=juga, Anda juga dapat mempertimbangkan oflag=seek_bytes.

Dari info dd:

`count_bytes'
      Interpret the `count=' operand as a byte count, rather than a
      block count, which allows specifying a length that is not a
      multiple of the I/O block size.  This flag can be used only
      with `iflag'.

`skip_bytes'
      Interpret the `skip=' operand as a byte count, rather than a
      block count, which allows specifying an offset that is not a
      multiple of the I/O block size.  This flag can be used only
      with `iflag'.

`seek_bytes'
      Interpret the `seek=' operand as a byte count, rather than a
      block count, which allows specifying an offset that is not a
      multiple of the I/O block size.  This flag can be used only
      with `oflag'.

P: Saya mengerti pertanyaan ini sudah tua dan sepertinya bendera ini diterapkan setelah pertanyaan awalnya diajukan, tetapi karena ini adalah salah satu hasil google pertama untuk pencarian dd terkait yang saya lakukan, saya pikir akan lebih baik untuk memperbarui dengan yang baru fitur.

Fabiano
sumber
2

Gunakan satu proses untuk membuang semua byte awal, lalu satu detik untuk membaca byte aktual, misalnya:

echo Hello, World\! | ( dd of=/dev/null bs=7 count=1 ; dd bs=5 count=1 )

Yang kedua dddapat membaca input dengan ukuran blok apa pun yang Anda rasa efisien. Perhatikan bahwa ini membutuhkan proses ekstra untuk melahirkan; tergantung pada OS Anda yang akan dikenakan biaya, tetapi mungkin lebih kecil daripada harus membaca file satu per satu byte (kecuali jika Anda memiliki file yang sangat kecil, dalam hal ini tidak akan ada masalah).

RolKau
sumber
Apakah ini akan bekerja dengan baik (yaitu tidak terlalu banyak memori) untuk offset dan jumlah yang besar? dd if=/dev/sda bs=10000000001 | dd bs=255 count=1 | hd-> "dd: angka tidak valid` 10000000001 '"
Vi.
@ Vi. Jika Anda ingin melewati offset besar maka Anda harus melakukan pembacaan awal sebagai serangkaian blok berukuran "idealnya" (tergantung sumber Anda) (16M), kemudian menjatuhkan serangkaian blok ukuran yang lebih kecil (512) yang akan berada dalam memori , untuk "memperbesar" pada data Anda, sebelum Anda menurunkan partion aneh yang tidak sesuai dengan ukuran blok (bs = 1 di bawah) dan kemudian membaca blok yang Anda inginkan. Misalnya Anda ingin membaca 255 byte dari offset 10000000001: dd if=/dev/sda bs=16M skip=596 count=1 | dd bs=512 skip=1522 count=1 | (dd bs=1 count=1 of=/dev/null ; dd bs=255 count=1)
RolKau
Tentunya akan lebih mudah digunakan read -nuntuk melompat? Lalu head -cmenghitung? Misalnya cat somefile | (read -n 1337; head -c 31337000)Atau Anda bisa melakukannya tanpa melahirkan proses tambahan:exec 3<somefile; read -n 1337 -u 3; head -c 31337000 <&3
Gannet
1

Alih-alih bs=1menggunakan bs=4096atau lebih.

ccpizza
sumber
2
Maka itu akan membaca dari offset 1337 * 4096 bukannya 1337
Vi.
1
Aha, begitu, mungkin akan lebih mudah untuk menulis skrip Python sederhana, misalnya seperti dalam contoh ini stackoverflow.com/questions/1035340/… dengan f.seek(1337)sebelum menggunakanread(MY_CHUNK_SIZE)
ccpizza
Rasanya seperti cara yang paling dapat diandalkan adalah dengan menulis custom executable. Beberapa sistem tidak memiliki Python, atau Ruby, atau bahkan Perl. : |
Trejkaz
1

Anda dapat mencoba perintah hexdump:

hexdump  -v <File Path> -c -n <No of bytes to read> -s <Start Offset>

Jika Anda hanya ingin melihat isinya:

#/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 #
Saravanan Palanisamy
sumber
Ini bukan tentang melihat file sebagai hex. Ini tentang mengekstraksi konten file (untuk menyalinnya di suatu tempat, misalnya) dari offset yang ditentukan dalam byte.
Vi.