以下の比較について専門家の提案が必要です:
ループを使用したコードセグメント:
for file in `cat large_file_list`
do
gzip -d $file
done
単純な拡張を使用したコードセグメント:
gzip -d `cat large_file_list`
どちらが速くなりますか?大きなデータセットを操作する必要があります。
以下は時々しか機能しません:
gzip -d `cat large_file_list`
3つの問題があります(bash
および他のほとんどのBourneのようなシェルで):
ファイル名にスペースタブまたは改行文字が含まれている場合は失敗します($IFS
が変更されていない場合)。これは、シェルの単語分割が原因です。
また、ファイル名にglob-active文字が含まれていると、失敗する可能性があります。これは、シェルがパス名展開をファイルリストに適用するためです。
また、ファイル名が-
で始まる場合(最初のファイルにのみ適用されるPOSIXLY_CORRECT=1
の場合)、またはファイル名が-
の場合も失敗します。
ファイル名が多すぎて1つのコマンドラインに収まらない場合も失敗します。
以下のコードには、上記のコードと同じ問題があります(4番目を除く)。
for file in `cat large_file_list`
do
gzip -d $file
done
large_file_list
のファイル名が1行に1つだけあり、-
というファイルがその中にない場合、GNUシステム上にいる場合は、次のように使用します。
xargs -rd'\n' gzip -d -- <large_file_list
-d'\n'
は、入力の各行を個別のファイル名として扱うようにxargs
に指示します。
-r
は、入力ファイルが空の場合、コマンドを実行しないようにxargs
に指示します。
--
は、次の引数が-
で始まっていても、オプションとして扱われないことをgzip
に伝えます。ただし、-
だけでは、-
というファイルではなく、-
として扱われます。
xargs
は、各コマンドラインに多くのファイル名を付けますが、コマンドラインの制限を超えるほどではありません。これにより、gzip
プロセスを開始する必要がある回数が減るため、これが高速になります。また、安全です。ファイル名もWord分割およびパス名展開から保護されます。
それが大事だとは思いません。
リストファイルにリストされているファイルの数がわからず、ファイル名の名前にスペースが含まれているかどうかが(一般的に)わからないため、ループを使用します。非常に長い引数のリストを生成するコマンド置換を実行すると、生成されたリストの長さが長すぎる場合に、「引数リストが長すぎます」というエラーが発生する可能性があります。
私のループは次のようになります
while IFS= read -r name; do
gunzip "$name"
done <file.list
これにより、gunzip
コマンドの後にデータを処理するためのコマンドを追加できます。実際、データが実際に何であり、それを使って何をする必要があるかに応じて、ファイルにまったく保存せずに処理することもできます。
while IFS= read -r name; do
zcat "$name" | process_data
done <file.list
(どこ process_data
は、非圧縮データを標準入力から読み取るパイプラインです)
データの処理にデータの圧縮解除よりも時間がかかる場合、ループがより効率的であるかどうかの問題は関係ありません。
理想的には、ファイル名のリストを使用せず、代わりに次のようにファイル名グロビングパターンを使用します
for name in ./*.gz; do
# processing of "$name" here
done
どこ ./*.gz
は、関連ファイルに一致するパターンです。この方法では、ファイルの数やファイル名に使用されている文字に依存しません(ファイルには改行やその他の空白文字が含まれている場合や、ダッシュなどで始まる場合があります)。
関連:
これらの2つのうち、gzip
を1回呼び出すだけでよいので、gzip
の1回の呼び出しにすべてのファイルが渡される方が高速になる可能性があります。 (つまり、コマンドがまったく機能する場合は、警告の他の回答を参照してください。)
しかし、私は ゴールデンの最適化ルール を思い出したいと思います:時期尚早にそれをしないでください。
問題であることを知る前に、そのようなことを最適化しないでください。
プログラムのこの部分には長い時間がかかりますか?さて、大きなファイルを解凍すると、とにかくそれを行わなければならないので、答えるのはそれほど簡単ではないかもしれません。
測定します。確かに、これが確実な最良の方法です。
結果は自分の目で(または独自のストップウォッチで)表示され、インターネットでのランダムな回答ではできない状況に適用されます。両方のバリアントをスクリプトに入れ、time script1.sh
およびtime script2.sh
を実行します。 (オーバーヘッドの絶対量を測定するには、空の圧縮ファイルのリストを使用してそれを行います。)
あなたのディスクはどれくらい速いですか?
これはすべてのCPUを使用するはずです。
parallel -X gzip -d :::: large_file_list
したがって、あなたの限界はおそらくあなたのディスクの速度になるでしょう。
-j
で調整してみてください:
parallel -j50% -X gzip -d :::: large_file_list
これにより、前のコマンドと同じようにジョブの半分が並行して実行され、ディスクにかかる負荷が少なくなるため、ディスクによってはこれが高速になる場合があります。