dd: wiele plików wejściowych


14

Muszę połączyć fragmenty z dwóch plików:

gdybym potrzebował połączyć całe pliki, mógłbym to zrobić

cat file1 file2 > output

Ale muszę pominąć pierwszy 1 MB z pierwszego pliku i chcę tylko 10 MB z drugiego pliku. Brzmi jak praca dla dd.

dd if=file1 bs=1M count=99 skip=1 of=temp1
dd if=file2 bs=1M count=10 of=temp2
cat temp1 temp2 > final_output

Czy jest to możliwe w jednym kroku? tzn. bez potrzeby zapisywania wyników pośrednich? Czy mogę używać wielu plików wejściowych dd?

Odpowiedzi:


21

dd może też pisać na standardowe wyjście.

( dd if=file1 bs=1M count=99 skip=1
  dd if=file2 bs=1M count=10  ) > final_output

To chyba najlepszy sposób. Plik wyjściowy nie jest zamknięty / ponownie otwarty (tak jak jest w przypadku oflag=append conv=notrunc), więc systemy plików, które dokonują opóźnionego przydzielania (jak XFS), mają najmniejszą szansę na stwierdzenie, że plik jest zapisywany, gdy jest jeszcze wiele do zrobienia.
Peter Cordes

@PeterCordes to dobry punkt, ale dopóki ddnie zostaniesz o to poproszony sync, opóźnione przydzielanie nie powinno i tak zostać natychmiast uruchomione (chyba że pamięć jest za mała, w którym to przypadku żadna metoda nie opóźni przydzielenia).
Stephen Kitt

@StephenKitt: Prawdopodobnie masz rację. Myślałem o spekulacyjnej wstępnej alokacji XFS , w której musi on specjalnie wykryć wzorzec dostępu zamykania / ponownego otwierania (czasami widziany dla plików dziennika).
Peter Cordes

3
W muszli, jak bashi mkshże nie optymalizuje się widelec do ostatniego polecenia w podpowłoce, można je nieco bardziej efektywny poprzez zastąpienie powłoki w tle z grupy poleceń. W przypadku innych powłok nie powinno to mieć znaczenia, a podejście do podpowłoki może być nawet nieco bardziej wydajne, ponieważ powłoka nie musi zapisywać i przywracać standardowego wyjścia.
Stéphane Chazelas

10

Nie sądzę, że możesz łatwo odczytać wiele plików w jednym ddwywołaniu, ale możesz dołączyć, aby zbudować plik wyjściowy w kilku krokach:

dd if=file1 bs=1M count=99 skip=1 of=final_output
dd if=file2 bs=1M count=10 of=final_output oflag=append conv=notrunc

Musisz określić zarówno, jak conv=notrunci oflag=append. Pierwszy unika obcięcia danych wyjściowych, drugi zaczyna pisać od końca istniejącego pliku.


8

Należy pamiętać, że ddjest surowy interfejs do read(), write()i lseek()wywołanie systemowe. Można go używać tylko w sposób niezawodny, aby wyodrębnić fragmenty danych ze zwykłych plików, zablokować urządzenia i niektóre urządzenia znakowe (np. /dev/urandom), Czyli pliki, których read(buf, size)powrót jest gwarantowany, sizedopóki nie zostanie osiągnięty koniec pliku.

W przypadku potoków, gniazd i większości urządzeń znakowych (takich jak ttys) nie masz takiej gwarancji, chyba że zrobisz read()to w rozmiarze 1 lub użyjesz ddrozszerzenia GNU iflag=fullblock.

Więc albo:

{
  gdd < file1 bs=1M iflag=fullblock count=99 skip=1
  gdd < file2 bs=1M iflag=fullblock count=10
} > final_output

Lub:

M=1048576
{
  dd < file1 bs=1 count="$((99*M))" skip="$M"
  dd < file2 bs=1 count="$((10*M))"
} > final_output

Lub z powłokami z wbudowanym wsparciem dla operatora wyszukiwania, takiego jak ksh93:

M=1048576
{
  command /opt/ast/bin/head -c "$((99*M))" < file1 <#((M))
  command /opt/ast/bin/head -c "$((10*M))" < file2
}

Lub zsh(zakładając, że headobsługuje tę -copcję tutaj):

zmodload zsh/system &&
{
  sysseek 1048576 && head -c 99M &&
  head -c 10M < file2
} < file1 > final_output

Czy naprawdę potrzebujesz cytatów? Czy wynik nie zawsze będzie liczbą całkowitą?
Steven Penny

@StevenPenny, pozostawiając rozszerzenie bez cudzysłowu, prosi powłokę o podzielenie + glob, co nie miałoby sensu. Część podzielona jest wykonywana na bieżącej wartości $IFS. Niezależnie od zawartości zmiennej / rozszerzenia. Zobacz także Implikacje bezpieczeństwa dla zapomnienia o cytowaniu zmiennej w powłokach bash / POSIX
Stéphane Chazelas

@ Stéphane Chazelas - w pierwszym przykładzie używasz gddzamiast dd. Czy to literówka, czy jest to celowe?
Martin Vegter

3

Dzięki bash ism i funkcjonalnie „bezużytecznemu użyciu cat ”, ale najbliższym składni, której używa OP:

cat <(dd if=file1 bs=1M count=99 skip=1) \
    <(dd if=file2 bs=1M count=10) \
   > final_output

(Biorąc to pod uwagę, odpowiedź Stephena Kitta wydaje się być najbardziej efektywną metodą).


3
Ściśle mówiąc, <(...)to kszizm, który zarówno skopiował, jak zshi obaj bash.
Stéphane Chazelas
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.