Voici comment vous pouvez le faire:
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
C'est tout ce qui est vraiment nécessaire - cela ne demande pas beaucoup plus. En premier lieu dd count=0 skip=1 bs=$block_size1
, lseek()
la saisie de fichiers régulière sur pratiquement instantanément. Il n'y a aucune chance de données manquées ou de tout autre mensonge qui soit dit à ce sujet, vous pouvez simplement rechercher directement la position de départ souhaitée. Étant donné que le descripteur de fichier appartient au shell et dd
que celui-ci ne fait que l'hériter, il affectera la position de son curseur et vous pourrez donc le suivre par étapes. C'est vraiment très simple - et il n'y a pas d'outil standard mieux adapté à la tâche que dd
.
Cela utilise une taille de bloc de 64k, ce qui est souvent idéal. Contrairement à la croyance populaire, les blocs plus grands ne rendent pas le dd
travail plus rapide. D'un autre côté, les petits tampons ne sont pas bons non plus. dd
doit synchroniser son temps dans les appels système afin qu'il n'ait pas besoin d'attendre la copie des données en mémoire et à nouveau, mais aussi pour qu'il n'ait pas besoin d'attendre les appels système. Vous voulez donc que cela prenne suffisamment de temps pour que le prochain read()
n'ait pas à attendre le dernier, mais pas tellement que vous tamponniez dans des tailles plus grandes que nécessaire.
Le premier dd
saute donc à la position de départ. Cela ne prend aucun temps. Vous pouvez appeler n'importe quel autre programme que vous aimiez à ce moment-là pour lire son stdin et il commencerait à lire directement à votre décalage d'octet souhaité. J'appelle un autre dd
pour lire les ((interval / blocksize) -1)
blocs de comptage sur stdout.
La dernière chose qui est nécessaire est de copier le module (le cas échéant) de l'opération de division précédente. Et c'est ça.
Soit dit en passant, ne le croyez pas quand les gens disent des faits sur leur visage sans preuve. Oui, il est possible dd
de faire une courte lecture (bien que de telles choses ne soient pas possibles lors de la lecture à partir d'un périphérique de bloc sain - d'où le nom) . De telles choses ne sont possibles que si vous ne mettez pas correctement en mémoire tampon un dd
flux lu à partir d'un périphérique autre qu'un bloc. Par exemple:
cat data | dd bs="$num" ### incorrect
cat data | dd ibs="$PIPE_MAX" obs="$buf_size" ### correct
Dans les deux cas, dd
copie toutes les données. Dans le premier cas, il est possible (bien que peu probable avec cat
) que certains des blocs de sortie qui copient soient des dd
octets "$ num" car dd
ils ne sont spécifiés que pour tamponner quoi que ce soit lorsque le tampon est spécifiquement demandé sur sa commande - ligne. bs=
représente une taille de bloc maximale car le but de ce module dd
est les E / S en temps réel.
Dans le deuxième exemple, je spécifie explicitement la taille de bloc de sortie et les dd
lectures de tampons jusqu'à ce que des écritures complètes puissent être effectuées. Cela n'affecte pas count=
ce qui est basé sur les blocs d'entrée, mais pour cela, vous avez juste besoin d'un autre dd
. Toute information erronée qui vous est donnée autrement doit être ignorée.
bs=1M iflag=skip_bytes,count_bytes