dd:複数の入力ファイル


13

2つのファイルからチャンクを連結する必要があります。

ファイル全体を連結する必要がある場合は、単に行うことができます

cat file1 file2 > output

ただし、最初のファイルから最初の1 MBをスキップする必要があり、2番目のファイルからは10 MBしか必要ありません。の仕事のように聞こえ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

ワンステップでこれを行う可能性はありますか?つまり、中間結果を保存する必要はありませんか?で複数の入力ファイルを使用できますddか?

回答:


21

dd 標準出力にも書き込むことができます。

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

これがおそらく最良の方法です。出力ファイルは(/のようにoflag=append conv=notrunc)クローズ/再オープンされないため、遅延割り当て(XFSなど)を行うファイルシステムは、まだ処理が残っているときにファイルの書き込みが完了したと判断する可能性が最も低くなります。
ピーターコーデス

@PeterCordesは良い点ですが、dd要求されない限りsync、遅延割り当てはすぐに開始されるべきではありません(メモリが不足していない限り、どちらの方法も割り当てを延期しません)。
スティーブンキット

@StephenKitt:あなたはおそらく正しい。XFSの投機的な事前割り当てを考えていました。そこでは、クローズ/再オープンアクセスパターン(ログファイルで見られることもある)を特別に検出する必要があります。
ピーターコーデス

3
以下のようなシェルではbashmkshサブシェル内の最後のコマンドのためのフォークを最適化していない、あなたは、コマンドグループでサブシェルを交換することによって、それは少しより効率的に行うことができます。他のシェルの場合、それは重要ではありません。また、シェルはstdoutを保存および復元する必要がないため、サブシェルのアプローチはわずかに効率的ですらあります。
ステファンシャゼル

10

1回のdd呼び出しで複数のファイルを簡単に読み取ることはできないと思いますが、いくつかの手順で出力ファイルをビルドするために追加できます。

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

conv=notruncとの両方を指定する必要がありますoflag=append。1つ目は出力の切り捨てを回避し、2つ目は既存のファイルの末尾から書き込みを開始します。


8

これddread()write()およびlseek()システムコールへの生のインターフェイスであることに注意してください。あなただけの通常のファイル、ブロックデバイスと(のようないくつかのキャラクタデバイスからデータのチャンクを抽出するために、確実にそれを使用することができ/dev/urandomたため、ファイルである、)read(buf, size)返すことが保証されてsizeいる限り、ファイルの終わりに達していないとして。

パイプ、ソケット、およびほとんどのキャラクターデバイス(ttyなど)の場合read()、サイズ1のs を実行するかGNU dd拡張機能を使用しない限り、そのような保証はありませんiflag=fullblock

どちらか:

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

または:

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

または、次のようなシーク演算子の組み込みサポートを備えたシェルを使用しksh93ます。

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

またはzsh(ここでオプションをheadサポートしていると仮定-c):

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

本当に引用符が必要ですか?結果は常に整数ではありませんか?
スティーブンペニー

@StevenPenny、展開を引用符で囲まずに残すことは、シェルにsplit + globを要求することで、ここでは意味がありません。の現在の値で行われている分割部分$IFS。これは、変数/展開の内容に関係ありません。参照してくださいbashの/ POSIXシェル内の変数を引用し忘れるのセキュリティへの影響
ステファン・Chazelas

@StéphaneChazelas-最初の例では、のgdd代わりに使用していますdd。それはタイプミスですか、それとも意図的なものですか?
Martin Vegter

3

bashのISM、および機能「の無駄な使用」が、構文に最も近いOPの用途:

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

(そうは言っても、Stephen Kittの答えは可能限り最も効率的な方法のようです。)


3
厳密に言えば、両方とコピーし<(...)クシズムです。zshbash
ステファンシャゼル16年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.