Come eseguire l'output del file dall'offset specificato, ma non "dd bs = 1 skip = N"?


28

Come fare cose del genere dd if=somefile bs=1 skip=1337 count=31337000, ma in modo efficiente, non usando letture e scritture non a 1 byte?

La soluzione è prevista:

  1. Per essere semplice (per non semplici posso scrivere un po 'di Perl oneliner che lo farà)
  2. Per supportare grandi offset e lunghezze (quindi gli hack con dimensioni del blocco in dd non aiuteranno)

Soluzione parziale (non abbastanza semplice, provare lo stesso con la lunghezza lo renderà ancora più complesso):

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

Stai cercando di cambiare la dimensione di blocco che sta usando dd?
cmorse

Modificato blocchi => unità modificate per saltare e contare
Vi.

Risposte:


37

Questo dovrebbe farlo (su gnu dd):

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

Nel caso in cui si utilizza seek=pure, si potrebbe anche prendere in considerazione oflag=seek_bytes.

Da 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'.

Ps: capisco che questa domanda è vecchia e sembra che questi flag siano stati implementati dopo che la domanda è stata originariamente posta, ma poiché è uno dei primi risultati di Google per una ricerca dd correlata, ho pensato che sarebbe bello aggiornarlo con il nuovo caratteristica.


2

Utilizzare un processo per eliminare tutti i byte iniziali, quindi un secondo per leggere i byte effettivi, ad esempio:

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

Il secondo ddpuò leggere l'input con qualsiasi dimensione di blocco che ritieni efficace. Si noti che ciò richiede la generazione di un processo aggiuntivo; a seconda del sistema operativo che comporta un costo, ma è probabilmente più piccolo della necessità di leggere i file uno per uno (a meno che non si disponga di un file molto piccolo, nel qual caso non ci sarebbe un problema).


Funzionerà bene (vale a dire non ingombrare troppa memoria) per grandi offset e conteggi? dd if=/dev/sda bs=10000000001 | dd bs=255 count=1 | hd-> "dd: numero non valido` 10000000001 '"
Vi.

@Vi. Se vuoi saltare un enorme offset, dovresti fare la lettura iniziale come una serie di blocchi di dimensioni "idealmente" (a seconda della sorgente) (16M), quindi rilasciare una serie di blocchi di dimensioni inferiori (512) che saranno in memoria , per "ingrandire" i tuoi dati, prima di eliminare una parte dispari che non si adatta alla dimensione del blocco (bs = 1 in basso) e quindi leggere il blocco desiderato. Ad esempio, si desidera leggere 255 byte dall'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

Sicuramente sarebbe più facile da usare read -nper saltare? E poi head -ccontare? Ad esempio, cat somefile | (read -n 1337; head -c 31337000)o potresti farlo senza generare un ulteriore processo:exec 3<somefile; read -n 1337 -u 3; head -c 31337000 <&3
Gannet,

1

Invece di bs=1usare bs=4096o di più.


2
Quindi leggerà dall'offset 1337 * 4096 invece che 1337
Vi.

1
Ah, vedo, allora sarà probabilmente più facile scrivere un semplice script Python, ad esempio come in questo esempio stackoverflow.com/questions/1035340/… con f.seek(1337)prima dell'usoread(MY_CHUNK_SIZE)
ccpizza

Sembra che il modo più affidabile sia probabilmente quello di scrivere un eseguibile personalizzato. Alcuni sistemi non dispongono di Python, Ruby o Perl. : |
Trejkaz,

1

Puoi provare il comando hexdump:

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

Se vuoi semplicemente vedere i contenuti:

#/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 #

Non si tratta di visualizzare il file come esadecimale. Si tratta di estrarre il contenuto di un file (per copiarlo da qualche parte, ad esempio) dall'offset specificato in byte.
Vi.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.