Como gerar o arquivo do deslocamento especificado, mas não “dd bs = 1 skip = N”?

28

Como fazer coisas como dd if=somefile bs=1 skip=1337 count=31337000, mas eficientemente, não usar leituras e gravações de 1 byte?

A solução é esperada:

  1. Para ser simples (para não-simples, eu posso escrever algum Perl oneliner que fará isso)
  2. Para suportar grandes desvios e comprimentos (para que hacks com tamanho de bloco no dd não ajudem)

Solução parcial (não é simples o suficiente, tentar o mesmo com comprimento tornará ainda mais complexo):

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.
fonte
Você está tentando alterar o tamanho do bloco que o dd está usando?
cmorse
Tamanho do bloco alterado => unidades alteradas para pular e contar
Vi.

Respostas:

37

Isso deve ser feito (no gnu dd):

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

Caso você esteja usando seek=também, você também pode considerar oflag=seek_bytes.

De 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: Entendo que essa pergunta é antiga e parece que essas sinalizações foram implementadas depois que a pergunta foi feita originalmente, mas como é um dos primeiros resultados do google para uma pesquisa de dd relacionada que eu fiz, achei interessante atualizar com o novo característica.

Fabiano
fonte
2

Use um processo para abandonar todos os bytes iniciais e, em seguida, um segundo para ler os bytes reais, por exemplo:

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

O segundo ddpode ler a entrada com qualquer tamanho de bloco que você achar eficiente. Observe que isso requer que um processo extra seja gerado; dependendo do seu sistema operacional, que terá um custo, mas provavelmente será menor do que ter que ler os arquivos um a um byte (a menos que você tenha um arquivo muito pequeno; nesse caso, não haveria problema).

RolKau
fonte
Funcionará bem (ou seja, não consumirá muita memória) para grandes compensações e contagens? dd if=/dev/sda bs=10000000001 | dd bs=255 count=1 | hd-> "dd: número inválido '10000000001'"
vi.
@Vi. Se você quiser pular um deslocamento enorme, faça a leitura inicial como uma série de blocos "idealmente" (dependendo da fonte) (16M) e solte uma série de blocos de tamanho menor (512) que estarão na memória , para "aumentar o zoom" nos seus dados, antes de soltar uma partição ímpar que não se encaixa no tamanho do bloco (bs = 1 abaixo) e depois ler o bloco desejado. Por exemplo, você deseja ler 255 bytes do deslocamento 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
Certamente seria mais fácil usar read -npara pular? E depois head -ccontar? Por exemplo cat somefile | (read -n 1337; head -c 31337000)Ou você poderia fazê-lo sem desova um processo adicional:exec 3<somefile; read -n 1337 -u 3; head -c 31337000 <&3
Gannet
1

Em vez de bs=1usar bs=4096ou mais.

ccpizza
fonte
2
Em seguida, lerá o deslocamento 1337 * 4096 em vez de 1337
Vi.
1
Aha, eu vejo, então provavelmente será mais fácil escrever um simples script Python, por exemplo, como neste exemplo stackoverflow.com/questions/1035340/... com f.seek(1337)antes de usarread(MY_CHUNK_SIZE)
ccpizza
Parece que a maneira mais confiável é provavelmente escrever um executável personalizado. Alguns sistemas não possuem Python, Ruby ou Perl. : |
Trejkaz
1

Você pode tentar o comando hexdump:

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

Se você simplesmente deseja ver o conteúdo:

#/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
fonte
Não se trata de visualizar o arquivo como hexadecimal. Trata-se de extrair o conteúdo de um arquivo (para copiá-lo em algum lugar, por exemplo) do deslocamento especificado em bytes.
Vi.