ディレクトリにたくさんのtar
ファイルがあり、それらからすべてのファイルを一度に抽出したいと考えています。しかし、これは何もしないようです:
$ tar xf *.tar
何が起きてる?大量のファイルを一度に untar するにはどうすればよいですか?
当初、このtar
コマンドは磁気テープ デバイスで使用することを目的としていました。一度に 1 つのデバイスでしか実行できないためtar
、構文は 1 つのデバイスのみを想定して設計されています。渡された最初のファイルまたはディレクトリは、問題のアーカイブと、アーカイブの内容が操作に含まれるその他のファイルまたはディレクトリを保持するデバイスであると想定されていました。したがって、tar
抽出 (x
オプション) の場合、最初に渡されたファイルがアーカイブになり、他のすべてのファイルが抽出されるファイルになります。したがって、2 つの*.tar
ファイル (たとえばa.tar
とb.tar
) がある場合、コマンドは次のように展開されます。
$ tar xf a.tar b.tar
a.tar
という名前のファイルが含まれていない限りb.tar
、tar
コマンドは何も実行せず、静かに終了します。厄介なことに、Solaris バージョンのtar
は、リターン コードまたは冗長オプション ( v
) で問題を報告しません。一方、冗長オプションをオフにしても、GNU tar
返品2
とスパムは次のようになります。STDERR
tar: b.tar: Not found in archive
tar: Exiting with failure status due to previous errors
複数のアーカイブ ファイルを入力として受け入れるには書き直すのが遅すぎtar
ますが、制限を回避するのはそれほど難しくありません。
ほとんどの人にとってtar
、複数のアーカイブに対して複数回実行することが最も適切なオプションです。ファイル名を 1 つだけ渡すtar xf
と、予想どおり、アーカイブされたすべてのファイルが抽出されます。1 つのアプローチは、シェルfor
ループを使用することです。
$ for f in *.tar; do tar xf "$f"; done
別の方法は、次を使用することxargs
です。
$ ls *.tar | xargs -i tar xf {}
または、多数の代替tar
ファイル リーダーの 1 つを使用することもできます。最後に、真に献身的なプログラマーはtar
、希望どおりに動作する置換を簡単に作成できます。形式は簡単で、多くのプログラミング言語には、ファイルを読み取るためのライブラリがありますtar
。たとえば、Perl プログラマーの場合は、Archive::Tar
モジュールを見てください。
やみくもに大量のファイルを untar すると、予期しない問題が発生する可能性があります。最も明白なのは、特定のファイル名が複数のtar
ファイルに含まれている可能性があることです。tar
はデフォルトでファイルを上書きするため、最終的に得られるファイルの正確なバージョンは、アーカイブが処理される順序によって異なります。さらに厄介なことに、この「巧妙な」最適化を試みると、ファイルのコピーが破損する可能性があります。
for f in *.tar; do
tar xf "$f" &
done
wait
と の両方a.tar
にb.tar
同じファイルが含まれていて、同時に抽出しようとすると、結果は予測できません。
関連する問題として、特に信頼できないソースからアーカイブを取得する場合に、tarbombが発生する可能性があります。
部分的な解決策の 1 つは、展開先の新しいディレクトリを自動的に作成することです。
for f in *.tar; do
d=`basename "$f" .tar`
mkdir "$d"
(cd "$d" && tar xf "../$f")
done
これは、ファイルが絶対パスでアーカイブに指定されている場合には役に立ちません (通常、これは悪意のある兆候です)。その種のチェックを追加することは、読者の演習として残されています。
すべての tar ファイルが同じフォルダーにある場合は、tcsh シェルでこれを行います。常に動作します。
find -iname \*.tar -exec tar -xvf {} \;
これは上記の回答と同じですが、もう少し簡潔だと思います。
find . -maxdepth 1 -name '*.tar' -exec tar -xf '{}' \;