Wie kann ich eine Datei mit dem angegebenen Versatz ausgeben, aber nicht "dd bs = 1 skip = N"?


28

Wie mache ich das so dd if=somefile bs=1 skip=1337 count=31337000, aber effizient, ohne 1-Byte-Lese- und Schreibzugriff?

Die Lösung wird erwartet:

  1. Um einfach zu sein (für Nicht-Einfache kann ich einige Perl-Oneliner schreiben, die dies tun)
  2. Um große Offsets und Längen zu unterstützen (so dass Hacks mit Blockgröße in dd nicht helfen)

Teillösung (nicht einfach genug, wenn Sie das Gleiche mit der Länge versuchen, wird es noch komplexer):

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

Versuchen Sie, die von dd verwendete Blockgröße zu ändern?
cmorse

Geänderte Blockgröße => geänderte Einheiten für Überspringen und Zählen
Vi.

Antworten:


37

Dies sollte es tun (auf gnu dd):

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

Wenn Sie seek=auch verwenden, können Sie auch in Betracht ziehen oflag=seek_bytes.

Von 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: Ich verstehe, dass diese Frage alt ist und es scheint, dass diese Flags implementiert wurden, nachdem die Frage ursprünglich gestellt wurde, aber da es eines der ersten Google-Ergebnisse für eine verwandte DD-Suche ist, die ich durchgeführt habe, wäre es schön, sie mit der neuen zu aktualisieren Feature.


2

Verwenden Sie einen Prozess, um alle anfänglichen Bytes zu löschen, und einen zweiten, um die tatsächlichen Bytes zu lesen, z.

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

Der zweite ddkann die Eingabe mit jeder Blockgröße lesen, die Sie für effizient halten. Beachten Sie, dass hierfür ein zusätzlicher Prozess erstellt werden muss. Abhängig von Ihrem Betriebssystem ist dies mit Kosten verbunden, aber wahrscheinlich ist es kleiner, als die Dateien einzeln zu lesen (es sei denn, Sie haben eine sehr kleine Datei, in diesem Fall liegt kein Problem vor).


Funktioniert es für große Offsets und Zählungen gut (dh beansprucht nicht zu viel Speicher)? dd if=/dev/sda bs=10000000001 | dd bs=255 count=1 | hd-> "dd: ungültige Nummer" 10000000001 "
Vi.

@Vi. Wenn Sie einen großen Versatz überspringen möchten, sollten Sie den ersten Lesevorgang als eine Reihe von Blöcken mit "idealer" (abhängig von Ihrer Quelle) Größe (16 MB) ausführen und dann eine Reihe von Blöcken mit geringerer Größe (512) ablegen, die sich im Speicher befinden , um Ihre Daten "zu vergrößern", bevor Sie eine ungerade Partition entfernen, die nicht zur Blockgröße passt (bs = 1 unten), und dann den gewünschten Block lesen. ZB möchten Sie 255 Bytes von Offset 10000000001 lesen: 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

Sicher wäre es einfacher read -nzu überspringen? Und dann head -czu zählen? ZB cat somefile | (read -n 1337; head -c 31337000)Oder Sie könnten es tun, ohne einen zusätzlichen Prozess exec 3<somefile; read -n 1337 -u 3; head -c 31337000 <&3
Gannet

1

Statt bs=1Verwendung bs=4096oder mehr.


2
Dann wird von Offset 1337 * 4096 statt 1337
Vi

1
Aha, ich sehe, dann wird es wahrscheinlich einfacher sein , einen einfachen Python - Skript zu schreiben, zum Beispiel wie in diesem Beispiel stackoverflow.com/questions/1035340/... mit f.seek(1337)vor der Verwendungread(MY_CHUNK_SIZE)
ccpizza

Am zuverlässigsten ist es wahrscheinlich, eine benutzerdefinierte ausführbare Datei zu schreiben. Einige Systeme haben weder Python noch Ruby oder sogar Perl. : |
Trejkaz

1

Sie können den Befehl hexdump ausführen:

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

Wenn Sie nur den Inhalt sehen wollen:

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

Es geht nicht darum, die Datei als Hex zu betrachten. Es geht darum, den Inhalt einer Datei aus dem angegebenen Offset in Bytes zu extrahieren (um sie beispielsweise irgendwo hin zu kopieren).
Vi.
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.