ディレクトリに多数のtar
ファイルがあり、それらからすべてのファイルを一度に抽出したい。しかし、これは何もしないようです:
$ tar xf *.tar
何が起きてる?一度に多数のファイルを展開するにはどうすればよいですか?
もともと、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
を返し、verboseオプションがオフの場合でもSTDERR
をスパムします。
tar: b.tar: Not found in archive
tar: Exiting with failure status due to previous errors
複数のアーカイブファイルを入力として受け入れるには、tar
を書き換えるのは遅すぎますが、制限を回避するのはそれほど難しくありません。
ほとんどの人にとって、複数のアーカイブに対してtar
を複数回実行することが最も便利なオプションです。 tar xf
にファイル名を1つだけ渡すと、予想どおりにすべてのアーカイブファイルが抽出されます。 1つのアプローチは、シェルfor
ループを使用することです。
$ for f in *.tar; do tar xf "$f"; done
別の方法は、xargs
を使用することです。
$ ls *.tar | xargs -i tar xf {}
または、いくつかの alternative tar
file readers のいずれかを使用できます。最後に、真に熱心なプログラマーは、希望どおりに動作するtar
置換を簡単に作成できます。 format は簡単で、多くのプログラミング言語にはtar
ファイルを読み込むためのライブラリがあります。たとえば、Perlプログラマーの場合、 Archive::Tar
モジュールをご覧ください。
大量のファイルをブラインドで展開すると、予期しない問題が発生する可能性があります。最も明白なのは、特定のファイル名が複数の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 '{}' \;