web-dev-qa-db-ja.com

乱雑なフォルダで解凍、de-tar -xvf --de-unarchiveする方法は?

通常、私は$ mkdir newFolder; $ mv *.Zip newFolder; $ cd newFolder; $unzip *.Zipでアーカイブを解除しますが、怠惰になって任意のフォルダー$ unzip *.Zipで行うことがあるため、他のコンテンツをときどき混乱させます。ここにいくつかの方法をリストします-いくつかのアーカイブバージョンは確かにくだらないフラグを持っていますが、他のバージョンはより質素です、私は後者にもっと興味があります。

アーカイブを解除する方法はいくつかありますが、他にありますか?

  1. $ find . -anewer fileThatExistedBeforeUnarchieving -ok rm '{}' \;弱点は、*.Zip dirsがリストされることです。そのため、遅い-okを使用する必要があり、*.Zipの一致が多く、遅いため、何らかの理由で、そうではないようです。抽出されたすべてに一致します。

  2. 抽出されたファイルが少量の場合、1つずつ、遅く、面倒で、エラーが発生しやすくなります。

  3. アーカイブのコンテンツが実際にフォルダであるかどうかを確認したい場合は、$ unzip -l *.bsdで確認することがあります。これは、少なくともobsdのunzipバージョンで機能します。

特定のアーカイブツールを参照している場合は、必要に応じてそれらを記述してください。ただし、シンプルにしてください。単一のツールではなく、その方法に関心があります。

14
user2362

名前で

アーカイブ内のファイルのリストを生成して削除することができますが、これは、ファイル名のプレーンリストを生成するオプションがないunzipや7zなどのアーカイバでは厄介です。 tarを使用しても、ファイル名に改行がないことを前提としています。

tar tf foo.tar | while read -r file; do rm -- "$file" done
unzip -l foo.Zip | awk '
    p && /^ --/ {p=2}
    p==1 {print substr($0, 29)}
    /^ --/ {++p}
' | while …
unzip -l foo.Zip | tail -n +4 | head -n -2 | while …  # GNU coreutils only
7z l -slt foo.Zip | sed -n 's/^Path = //p' | while …  # works on tar.*, Zip, 7z and more

ファイルを削除する代わりに、目的の宛先にファイルを移動することができます。

tar tf foo.tar | while read -r file; do
  if [ -d "$file" ]; then continue; fi
  mkdir -p "/intended/destination/${file%/*}"
  mv -- "$file" "/intended/destination/$file"
done

ヒューズの使用

外部ツールに依存する代わりに、(ほとんどのユニスで) Fuse を使用して、通常のファイルシステムコマンドを使用してアーカイブを操作できます。

Fuse-Zip を使用して、Zipをのぞき見したり、cpで抽出したり、その内容をfindでリストしたりできます。

mkdir /tmp/foo.d
Fuse-Zip foo.Zip /tmp/foo.d
## Remove the files that were extracted mistakenly (GNU/BSD find)
(cd /tmp/foo.d && find . \! -type d -print0) | xargs -0 rm
## Remove the files that were extracted mistakenly (zsh)
rm /tmp/foo.d/**(:"s~/tmp/foo.d/~~"^/)
## Extract the contents where you really want them
cp -Rp /tmp/foo.d /intended/destination
fusermount -u foo.d
rmdir foo.d

[〜#〜] avfs [〜#〜] は、すべてのアーカイブに関連付けられたディレクトリ(最後に#が付いた同じ名前)を持つディレクトリ階層全体のビューを作成します。アーカイブコンテンツを保持しているようです。

mountavfs
## Remove the files that were extracted mistakenly (GNU/BSD find)
(cd ~/.avfs/"$PWD/foo.Zip#" && find . \! -type d -print0) | xargs -0 rm
## Remove the files that were extracted mistakenly (zsh)
rm ~/.avfs/$PWD/foo.Zip\#/**/*(:"s~$HOME/.avfs/$PWD/foo.Zip#~~"^/)
## Extract the contents where you really want them
cp -Rp ~/.avfs/"$PWD/foo.Zip#" /intended/destination
umountavfs

日付別

抽出以外のアクティビティが同じ階層になかったとすると、抽出されたファイルは、最近の ctimeでわかります。 -) 。 Zipファイルを作成または移動したばかりの場合は、カットオフとして使用できます。それ以外の場合はls -lctr適切なカットオフ時間を決定します。 zipを削除しないようにしたい場合は、手動で承認する理由はありません。findはzipを完全に除外できます。 zshまたはfindを使用したコマンドの例を次に示します。 -cminおよび-cnewerプライマリはPOSIXにはありませんが、Linux(およびGNU find)、* BSD、OSXを備えた他のシステム)に存在します。

find . \! -name '*.Zip' -type f -cmin -5 -exec rm {} +  # extracted <5 min ago
rm **/*~*.Zip(.cm-6)  # zsh, extracted ≤5 min ago
find . -type f -cnewer foo.Zip -exec rm {} +  # created or moved after foo.Zip

GNU find、FreeBSDおよびOSXで、カットオフ時間を指定する別の方法は、ファイルを作成し、touchを使用してそのmtimeをカットオフ時間に設定することです。

touch -d … cutoff
find . -type f -newercm cutoff -delete

ファイルを削除する代わりに、目的の宛先にファイルを移動することができます。これは、GNU/* BSD/OSX検索を使用して、必要に応じて宛先にディレクトリを作成する方法です。

find . \! -name . -cmin -5 -type f -exec sh -c '
    for x; do
      mkdir -p "$0/${x%/*}"
      mv "$x" "$0/$x"
    done
  ' /intended/destination {} +

Zshと同等(ほぼ:これは、ファイルを含むディレクトリだけでなく、ディレクトリ階層全体を再現します):

autoload zmv
mkdir -p ./**/*(/cm-3:s"|.|/intended/destination|")
zmv -Q '(**/)(*)(.cm-3)' /intended/destination/'$1$2'

警告、私はこの回答のほとんどのコマンドをテストしていません。削除する前に、必ずファイルのリストを確認してください(最初にechoを実行し、次にrmを実行して問題がない場合)。

Zshで次の関数を使用します。


ununzip () {
    rm -r $(unzip -l $1 | grep -v 'Archive:' | \
    grep '[/.]' | sed 's![^a-zA-Z]([a-zA-Z./])!\1!')
}

つまりunzip -lのクリーンアップされた出力内のすべてのファイルを削除するコマンド置換。

tar tvfも同様の方法で使用できます。

0
Edd Steel

実際にはあなたが求めていたものではありませんが、代わりに「すべて解凍」スクリプトを使用する方法について説明します。

unzip *.Zip

このようにして、各ファイルからの出力はそれ自体のディレクトリに送られます。

#!/bin/bash
for f in *.Zip ; do unzip -n "$f" -d "${f/%Zip/out}"; done
0
Johan