É assim que você pode fazer isso:
i=$(((t=19876543212)-(h=12345678901)))
{ dd count=0 skip=1 bs="$h"
dd count="$((i/(b=64*1024)-1))" bs="$b"
dd count=1 bs="$((i%b))"
} <infile >outfile
Isso é tudo o que é realmente necessário - não requer muito mais. Em primeiro lugar, dd count=0 skip=1 bs=$block_size1
irá lseek()
sobre a entrada regular de arquivos praticamente instantaneamente. Não há chance de dados perdidos ou quaisquer outras mentiras contadas a respeito, basta procurar diretamente a posição inicial desejada. Como o descritor de arquivo pertence ao shell e o dd
meramente o está herdando, eles afetarão sua posição do cursor e, portanto, você poderá segui-lo em etapas. É realmente muito simples - e não há ferramenta padrão mais adequada para a tarefa do que dd
.
Isso usa um tamanho de bloco de 64k, o que geralmente é ideal. Ao contrário da crença popular, tamanhos maiores de blocos não tornam o dd
trabalho mais rápido. Por outro lado, tampões minúsculos também não são bons. dd
precisa sincronizar seu tempo nas chamadas do sistema para que não precise esperar a cópia dos dados na memória e para fora novamente, mas também para que não precise esperar nas chamadas do sistema. Portanto, você quer que demore tempo suficiente para que o próximo read()
não precise esperar pelo último, mas não tanto que você esteja armazenando buffer em tamanhos maiores do que o necessário.
Então o primeiro dd
pula para a posição inicial. Isso leva tempo zero . Você poderia ligar para qualquer outro programa que você gostasse naquele momento para ler o stdin e ele começaria a ler diretamente no deslocamento de bytes desejado. Eu chamo outro dd
para ler ((interval / blocksize) -1)
blocos de contagem para stdout.
A última coisa necessária é copiar o módulo (se houver) da operação de divisão anterior. E é isso.
A propósito, não acredite quando as pessoas demonstram fatos sem comprovação. Sim, é possível dd
fazer uma leitura curta (embora essas coisas não sejam possíveis ao ler a partir de um dispositivo de bloco íntegro - portanto, o nome) . Essas coisas só são possíveis se você não armazenar em buffer corretamente um dd
fluxo lido de outro dispositivo que não seja um bloco. Por exemplo:
cat data | dd bs="$num" ### incorrect
cat data | dd ibs="$PIPE_MAX" obs="$buf_size" ### correct
Nos dois casos, dd
copia todos os dados. No primeiro caso, é possível (embora improvável cat
) que alguns dos blocos de saída copiados tenham dd
bits iguais a "$ num" bytes porque dd
são especificados apenas para armazenar em buffer qualquer coisa quando o buffer for solicitado especificamente em seu comando. linha. bs=
representa um tamanho máximo de bloco porque o objetivo de dd
é a E / S em tempo real.
No segundo exemplo, especifico explicitamente o tamanho do bloco de saída e as dd
leituras dos buffers até que as gravações completas possam ser feitas. Isso não afeta o count=
que é baseado em blocos de entrada, mas para isso você só precisa de outro dd
. Qualquer informação incorreta que lhe seja fornecida deve ser desconsiderada.
bs=1M iflag=skip_bytes,count_bytes