Comment sortir un fichier à partir de l'offset spécifié, mais pas «dd bs = 1 skip = N»?

28

Comment faire des choses comme dd if=somefile bs=1 skip=1337 count=31337000, mais efficacement, sans utiliser des lectures et des écritures non à 1 octet?

La solution est attendue:

  1. Pour être simple (pour les non-simples, je peux écrire un onliner Perl qui le fera)
  2. Pour prendre en charge les grands décalages et longueurs (donc les hacks avec une taille de bloc en dd ne seront pas utiles)

Solution partielle (pas assez simple, essayer la même chose avec la longueur le rendra encore plus complexe):

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.
la source
Essayez-vous de changer la taille de bloc utilisée par dd?
cmorse
Taille de bloc modifiée => unités modifiées pour sauter et compter
Vi.

Réponses:

37

Cela devrait le faire (sur gnu dd):

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

Si vous utilisez seek=également, vous pouvez également envisager 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: Je comprends que cette question est ancienne et il semble que ces indicateurs aient été mis en œuvre après la question posée à l'origine, mais comme il s'agit de l'un des premiers résultats de Google pour une recherche dd connexe que j'ai faite, je pensais que ce serait bien de mettre à jour avec la nouvelle fonctionnalité.

Fabiano
la source
2

Utilisez un processus pour abandonner tous les octets initiaux, puis un second pour lire les octets réels, par exemple:

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

Le second ddpeut lire l'entrée avec n'importe quelle taille de bloc que vous trouvez efficace. Notez que cela nécessite un processus supplémentaire pour être généré; en fonction de votre système d'exploitation, cela entraînera un coût, mais il est probablement plus petit que d'avoir à lire les fichiers un par un (sauf si vous avez un très petit fichier, auquel cas il n'y aurait pas de problème).

RolKau
la source
Cela fonctionnera-t-il bien (c.-à-d. Ne monopolise pas trop de mémoire) pour les grands décalages et les grands nombres? dd if=/dev/sda bs=10000000001 | dd bs=255 count=1 | hd-> "dd: numéro invalide` 10000000001 '"
Vi.
@Vi. Si vous voulez sauter un énorme décalage, vous devez faire la lecture initiale comme une série de blocs de taille "idéalement" (selon votre source) (16M), puis supprimer une série de blocs de taille inférieure (512) qui seront en mémoire , pour "zoomer" sur vos données, avant de déposer une partie impaire qui ne correspond pas à la taille du bloc (bs = 1 ci-dessous), puis de lire le bloc souhaité. Par exemple, vous voulez lire 255 octets du décalage 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
Ce serait sûrement plus facile à utiliser read -npour sauter? Et puis head -ccompter? Par exemple, cat somefile | (read -n 1337; head -c 31337000)ou vous pouvez le faire sans engendrer un processus supplémentaire:exec 3<somefile; read -n 1337 -u 3; head -c 31337000 <&3
Fou de Bassan
1

Au lieu d' bs=1utiliser bs=4096ou plus.

ccpizza
la source
2
Ensuite, il lira le décalage 1337 * 4096 au lieu de 1337
Vi.
1
Aha, je vois, alors il sera probablement plus facile d'écrire un simple script Python, par exemple comme dans cet exemple stackoverflow.com/questions/1035340/… avec f.seek(1337)avant d'utiliserread(MY_CHUNK_SIZE)
ccpizza
Il semble que le moyen le plus fiable soit probablement d'écrire un exécutable personnalisé. Certains systèmes n'ont ni Python, ni Ruby, ni même Perl. : |
Trejkaz
1

Vous pouvez essayer la commande hexdump:

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

Si vous voulez simplement voir le contenu:

#/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
la source
Il ne s'agit pas de visualiser le fichier en hexadécimal. Il s'agit d'extraire le contenu d'un fichier (pour le copier quelque part, par exemple) à partir du décalage spécifié en octets.
Vi.