フォルダーに含まれる.gzファイルの抽出


13

約320116の.pdb.gzファイルを含むフォルダーがあります。それらをすべて圧縮解除します。gunzip * .gzを使用すると、エラー、つまり引数リストが長すぎます。フォルダーは約2GBです。適切な提案をお願いします。


長期的にこのディレクトリ構造で作業する必要がある場合は、このディレクトリを多くのディレクトリに分割してください。たとえば、ファイルの変更時間またはファイル名に基づきます。
ダン

はい、私は長期的に働く必要があります。それらは抽出されたので、名前に基づいて3つのフォルダに細分化して分類したいと思います。そのためのシェルスクリプトはありますか?
リリーシャープトン

そこで同様の質問を検索することをお勧めします。ニーズに合ったものが見つからない場合は、新しい質問をしてください。
ダン

回答:


26
find . -name '*.pdb.gz' -exec gunzip {} +

-exec gunzip {} +gunzipコマンドラインで多くのファイル名を提供しますが、多すぎません。これは、すべてのファイルに対して-exec gunzip {} \;新しいgunzipプロセスを開始するよりも効率的です。


3
1 find、少ないgunzip
ダン

2
「+」はGNUismであるため、* BSDのような非GNUシステムでは機能しないことに注意してください。
モニカ

3
BSDの以降のバージョンでfindは、「+」表記が許可されています。例えば、参照BSD 10.1のmanページを。OS X(少なくとも10.9以降、おそらくそれ以前)にも適用されます。find
プラズマ

7

「引数リストが長すぎます」というエラーが表示されるたびに、使用する引数のサブセットを使用して、目的のコマンドを複数回呼び出すことで回避できます。xargsそれを自動的に行うのに役立つツールです。

find . -type f -a -name \*.pdb.gz -print0 | xargs -0 gunzip

これは、-execdir gunzip "{}" \;xargsがファイルごとにgunzipを個別に起動するのと同じ非効率ではないのですか?それがマニュアルページの私の読書です。
gogoud

5
いいえ、コマンドラインにxargs収まるだけのファイル名を詰め込みますgunzip。それを試してみてください!6つの引数すべてで1回echo a b c d e f | xargs echoだけ呼び出すechoので、1行の出力が表示されますが(実行するのにかなり役に立たないコマンド!!!!)xargs、コマンドの呼び出しごとに最大3つの引数のみを強制的に提供すると、echo a b c d e f | xargs -n 3 echo2行の出力が得られます。
セラダ

4
使用のもう1つの利点はxargs、この-Pオプションを使用すると、複数のgunzipプロセスを並行して実行できることです(システムの正確なパラメーターによって異なります)。
psmears

-P、@ psmears へのポインタに感謝します。今、も何か学びました!
セラダ

1

これはうまくいくと思う、各ファイルのパス/名前を個別にgunzipに渡して処理する:

find /my/dir -name "*.pdb.gz" -execdir gunzip "{}" \;

1
これは、ファイルごとに1回gunzipを実行します。その非効率性を回避するわずかに異なる方法については、John1024の回答を参照してください。
セラダ

@Celadaこれは意図的なものでした。私の懸念は、gunzipのオーバーロードが原因で+を使用すると再びエラーメッセージが表示される可能性があることです。John1024の方法が機能する場合、技術的にはより効率的ですが、機能しない場合は機能するはずです。
-gogoud

1
find+し、xargs明示心の中でまさにその問題とデザイナーです。オペレーティングシステムの制限を超えない限り、常に可能な限り多くの引数を提供します。ちなみに、これオペレーティングシステムの制限であり、とは関係ありませんgunzip
セラダ

1
@Celadaはその情報に感謝します。したがって、おそらく「+」でgunzipが複数回呼び出される可能性がありますが、320,000回未満ですか?
gogoud

1
正しい。
セラダ

1

この方法を試してください:

find . -name '*.gz' -exec gunzip {} \;

3
これはgunzipファイルごとに1回実行されます。その非効率性を回避するわずかに異なる方法については、John1024の回答を参照してください。
セラダ

* .gzの*を必ずエスケープしてください。
user253751

1

マルチコアマシンを使用してgunzipいる場合、使用してもマシンの機能が最大限に発揮されない可能性があります。そのためには、複数gunzipのを並行して実行する必要があります。どちらの端末で手作業で行われているのかを追跡するのは面倒ですが、GNUパラレルで簡単に行うことができます。

find . -name "*.gz" | parallel -X gunzip {}

1
引数リストparallelが長すぎるため失敗しませんか?
user253751

はい@immibis、私は元の問題を忘れてしまった、私は私のポストを更新します
Anthonの

への引数リストが長すぎるため、それでも失敗しませんfindか?
user253751

1
はい、ただし、findコマンドラインですべてのファイル名を渡します。
user253751

私は、引数を引用するのを忘れ、これは質問に答えるために良い一日ではないようです-name
Anthonの

-1

findサブフォルダーについては言及しなかったため、これを使用する必要はありません。あなたがする必要があるのは:

for f in *.gz;do gunzip $f;done

4
あなたは行う必要性をfindあなたは320116の産卵したくない場合はgunzip、このループはありません同じように、プロセスを。
ジョンWHスミス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.