Jak wyprowadzić plik z określonego przesunięcia, ale nie „dd bs = 1 skip = N”?

28

Jak zrobić coś takiego dd if=somefile bs=1 skip=1337 count=31337000, ale wydajnie, nie używając nieczytelnych odczytów i zapisów?

Oczekiwane jest rozwiązanie:

  1. Mówiąc prościej (dla nie-prostych mogę napisać perel oneliner, który to zrobi)
  2. Do obsługi dużych przesunięć i długości (więc hacki o rozmiarze bloku w dd nie pomogą)

Częściowe rozwiązanie (nie dość proste, próba tego samego z długością sprawi, że będzie jeszcze bardziej skomplikowana):

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.
źródło
Czy próbujesz zmienić rozmiar bloku, którego używa dd?
cmorse
Zmieniono rozmiar bloku => zmieniono jednostki do pominięcia i zliczenia
Vi.

Odpowiedzi:

37

To powinno to zrobić (na gnu dd):

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

Jeśli również używasz seek=, możesz również rozważyć oflag=seek_bytes.

Od 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: Rozumiem, że to pytanie jest stare i wydaje się, że te flagi zostały zaimplementowane po tym, jak pytanie zostało pierwotnie zadane, ale ponieważ jest to jeden z pierwszych wyników google dla pokrewnego wyszukiwania dd, które zrobiłem, myślę, że byłoby miło zaktualizować za pomocą nowego cecha.

Fabiano
źródło
2

Użyj jednego procesu, aby porzucić wszystkie początkowe bajty, a następnie drugiego, aby odczytać rzeczywiste bajty, np .:

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

Drugi ddmoże odczytać dane wejściowe przy dowolnym rozmiarze bloku, który uważasz za skuteczny. Zauważ, że wymaga to dodatkowego procesu do odrodzenia; w zależności od systemu operacyjnego, który będzie ponosił koszty, ale prawdopodobnie jest mniejszy niż konieczność czytania plików jeden po drugim bajcie (chyba że masz bardzo mały plik, w którym to przypadku nie będzie problemu).

RolKau
źródło
Czy będzie działał dobrze (tzn. Nie będzie zbyt dużej pamięci) przy dużych przesunięciach i liczeniach? dd if=/dev/sda bs=10000000001 | dd bs=255 count=1 | hd-> „dd: nieprawidłowy numer„ 10000000001 ””
Vi.
@Vi. Jeśli chcesz pominąć ogromne przesunięcie, powinieneś zrobić początkowy odczyt jako serię bloków o „idealnie” (w zależności od źródła) (16M), a następnie upuść serię bloków o mniejszych rozmiarach (512), które będą w pamięci , aby „powiększyć” swoje dane, przed upuszczeniem nieparzystej części, która nie pasuje do rozmiaru bloku (bs = 1 poniżej), a następnie odczytaniem żądanego bloku. Np. Chcesz odczytać 255 bajtów z offsetu 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
Z pewnością łatwiej read -nbyłoby pominąć? A potem head -cliczyć? Np. cat somefile | (read -n 1337; head -c 31337000)Albo możesz to zrobić bez odradzania dodatkowego procesu:exec 3<somefile; read -n 1337 -u 3; head -c 31337000 <&3
Gannet,
1

Zamiast bs=1używać bs=4096lub więcej.

ccpizza
źródło
2
Następnie odczyta z przesunięcia 1337 * 4096 zamiast 1337
Vi.
1
Aha, rozumiem, wtedy prawdopodobnie łatwiej będzie napisać prosty skrypt w Pythonie, np. Jak w tym przykładzie stackoverflow.com/questions/1035340/... z f.seek(1337)przed użyciemread(MY_CHUNK_SIZE)
ccpizza 21.01.12
Wydaje się, że najbardziej niezawodnym sposobem jest prawdopodobnie napisanie niestandardowego pliku wykonywalnego. Niektóre systemy nie mają Pythona, Ruby, a nawet Perla. : |
Trejkaz
1

Możesz wypróbować polecenie hexdump:

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

Jeśli chcesz po prostu zobaczyć zawartość:

#/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
źródło
Nie chodzi o wyświetlanie pliku jako heksadecymalnego. Chodzi o wyodrębnienie zawartości pliku (na przykład, aby go gdzieś skopiować) z określonego przesunięcia w bajtach.
Vi.