web-dev-qa-db-ja.com

一度に複数のファイルを展開するにはどうすればよいですか?

ディレクトリに多数のtarファイルがあり、それらからすべてのファイルを一度に抽出したい。しかし、これは何もしないようです:

$ tar xf *.tar

何が起きてる?一度に多数のファイルを展開するにはどうすればよいですか?

65
Jon Ericson

何が起きてる?

もともと、tarコマンドは、磁気テープデバイスで使用するためのものでした。一度に1つのデバイスでtarを実行するだけの意味があるため、構文は1つのデバイスのみを想定して設計されています。渡された最初のファイルまたはディレクトリは、問題のアーカイブと、操作にアーカイブの内容が含まれるその他のファイルまたはディレクトリを保持するデバイスであると想定されていました。したがって、tar抽出(xオプション)の場合、最初に渡されるファイルはアーカイブになり、他のすべてのファイルは抽出されるファイルになります。したがって、2つの*.tarファイル(たとえばa.tarb.tar)がある場合、コマンドは次のように展開されます。

$ tar xf a.tar b.tar

a.tarb.tarという名前のファイルが含まれていない限り、tarコマンドは何も実行せず、静かに終了します。面倒なことに、Solarisバージョンのtarは、戻りコードまたは冗長オプション(v)で問題を報告しません。一方、GNU tar2を返し、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.tarb.tarの両方に同じファイルが含まれていて、同時にそれを抽出しようとすると、結果は予測できません。

関連する問題は、特に信頼できないソースからアーカイブを取得する場合、 tarbomb の可能性です。

1つの部分的な解決策は、抽出する新しいディレクトリを自動的に作成することです。

for f in *.tar; do 
  d=`basename "$f" .tar`
  mkdir "$d"
  (cd "$d" && tar xf "../$f")
done

これは、ファイルが絶対パス(通常は悪意の兆候である)でアーカイブに指定されている場合は役に立ちません。この種のチェックを追加することは、読者の課題として残されています。

129
Jon Ericson

すべてのtarファイルが同じフォルダーにある場合、tcshシェルでこれを行います。常に機能します。

find -iname \*.tar -exec tar -xvf {} \;

これは上記の答えと同じですが、もう少し簡潔に思います。

11
Snehashis Roy
find . -maxdepth 1 -name '*.tar' -exec tar -xf '{}' \;
5
user3734617