web-dev-qa-db-ja.com

Zipファイルを「抽出」する方法

Zipファイルを空でないフォルダに抽出しました。 Zipファイルには、多数のファイルと深い階層があり、ターゲットディレクトリの既存のツリーとマージされています。すでに存在していたファイルとディレクトリを破壊せずに解凍によって作成されたファイルとディレクトリを削除するにはどうすればよいですか?もちろん、私はマージしたZipファイルをまだ持っているので、情報はそこにあります。

52
mafp

jjlin の答えは進むべき道です。ディレクトリの選択肢をいくつか追加したいだけです。

  • 抽出されたファイルをすべて削除し、ディレクトリは削除しない

    unzip -lqq file.Zip | gawk -F"  " '{print $NF;}' |
      while IFS= read -r n; do rm "$n"; done
    
  • 抽出されたファイルとemptyディレクトリのみを削除します

    unzip -lqq file.Zip | gawk -F"  " '{print $NF;}' |
      while IFS= read -r n; do rm "$n"; done; rmdir *
    

    オプションを指定しない場合、rmdirは空のディレクトリのみを削除し、ファイルと空でないフォルダをそのまま残して、*で安全に実行できるようにします。

  • 削除すべてを抽出しましたが、削除する前に確認を求めます:

    unzip -lqq file.Zip | gawk -F"  " '{print $NF;}' |
      while IFS= read -r n; do rm -ri "$n"; done; rmdir *
    

    -iフラグを使用すると、削除する前にrmでプロンプトが表示されます。[はい]または[いいえ]を選択できます。

  • 削除すべて抽出、ディレクトリを含む:

    unzip -lqq file.Zip | gawk -F"  " '{print $NF;}' |
      while IFS= read -r n; do rm -rf "$n"; done
    
28
terdon

unzip -lqq <filename.Zip>を使用して、Zipファイルの内容を一覧表示できます。ただし、これには、除外する必要があるいくつかの無関係な情報が含まれます。これは私のために働くコマンドです:

unzip -lqq file.Zip | awk '{print $4;}' | xargs rm -rf

awkコマンドは、ファイルとディレクトリの名前のみを抽出します。その後、結果はxargsに渡されてすべて削除されます。結果が正しいことを確認するために、最初にコマンドの予行演習を行う(つまり、xargs rm -rfの部分を省略して)ことをお勧めします。

上記のコマンドでは、空白があるパスを処理する際に問題が発生します。この(より複雑な)バージョンはそれを修正する必要があります:

unzip -lqq file.Zip | awk '{$1=$2=$3=""; sub(/ */, "", $0); printf "%s%s", $0, "\0"}' | xargs -0 rm -rf
28
jjlin

スイッチ-Z1を使用すると、unzipは1行に1つのファイルのみをリストします(それ以外は何も表示しません)。

このように、あなたは使うことができます

unzip -Z1 | xargs -I {} rm '{}'

zipファイルから抽出されたすべてのファイルを削除します。

コマンド

unzip -Z1 | xargs -I {} rm -rf '{}'

ディレクトリも削除されますが、注意する必要があります。 Zipファイルを抽出する前にディレクトリがすでに存在していた場合、それらのディレクトリ内の既存のファイルもすべて削除されます。


とにかくZipファイルを再抽出する場合は、奇妙なファイル名を処理することが保証されている別のアプローチがあります。

最初に、本来それを抽出するつもりだったZipファイルを抽出します。

unzip file.Zip -d elsewhere

ここで、誤ってファイルを抽出したディレクトリに移動し、次のコマンドを実行します。

find elsewhere -type f -printf "%P\0" | xargs -0 -I {} rm '{}'
  • -type fはファイルのみを検索します(ディレクトリは検索しません)。

  • %P\0は相対パス(elsewhere/なし)で、その後にnull文字が続きます。

  • -0は、xargsをnull文字で行を分けます。これは、理論的にはファイル名に改行文字を含めることができるため、より信頼性が高くなります。


残ったディレクトリを処理するには、次のコマンドを実行します。

find -type d -exec rmdir -p {} \; 2> /dev/null
  • -type dはディレクトリのみを検索します。

  • -exec rmdir -p {} \;は、見つかったすべてのディレクトリに対してrmdir -p {}を実行します。

    {}は検出されたディレクトリであり、-pスイッチはrmdirに空の親ディレクトリも削除させます。

  • 2> /dev/nullは、空ではないディレクトリまたは以前に削除されたディレクトリを削除しようとすると発生するエラーメッセージを抑制します。


関連するmanページ:

11
Dennis

これはさらに簡単で安全な(私は思う)ソリューションです

Zip -m getmeoutofhere.Zip `unzip -lqq myoriginalzipfile.Zip`
rm getmeoutofhere.Zip

これが何をしているか:バッククォートされたunzipコマンドは、元のファイルの内容のリストを生成します。

次に、Zip -mはそのリストを使用して、それぞれをgetmeoutofhere.Zipに追加しますそして、元のディレクトリから削除します(したがって、理論的には、myoriginalfile.Zipのインデントである必要があります。

マイナス面はnzip -lqqが余分なテキスト、日付、時間、ファイルサイズなどを生成することです。これらはZip -mにエラーメッセージを生成させますが、これは何の影響もないはずです(可能性が低い場合を除く)同じ名前のファイルの場合)。

これは、元の解凍中に作成されたディレクトリを削除しないことに注意してください。

2
David E.

アーカイブ内の変更タイムスタンプが抽出されたコピーに保持されないようにファイルを抽出した場合(ただし、抽出されたファイルには通常の変更時刻があります)、これを攻撃する正しい方法は変更時刻を経由することです。抽出されたすべてのファイルには、そのディレクトリで最後に変更された既存のファイルよりも新しい変更タイムスタンプがあります。

これは簡単な状況です。

現在のディレクトリにある既存のファイルが少なくとも24時間は変更されていないとします。したがって、過去24時間に変更されたものはすべて、zipファイルのジャンクです。

$ find . -mtime -1 -print0 | xargs -0 rm

これもいくつかのディレクトリを見つけますが、rmはそれらをそのままにします。それらは2番目のパスで処理できます。

$ find . -mtime 1 -type d -print 0 | xargs -0 rmdir

最近変更されたディレクトリはすべてZipによって変更されました。 rmdirがそれらを正常に削除した場合、それらは空であることを意味します。 Zipによって操作された空のディレクトリは、おそらくZipによって作成されたものです。つまり、アーカイブからのものです。 100%確信することはできません。解凍ジョブにより、いくつかのファイルが空の既存のディレクトリに置かれた可能性があります。

ツリー内のファイルが最近変更されたため、findの24時間の粒度がジョブにとって十分ではない場合、次に簡単なものを検討します。解凍ジョブが既存のサブディレクトリに何も配置しなかったとします。 。つまり、解凍されたものはすべて、最上位レベルのファイルか、以前には存在しなかった新しいサブディレクトリのいずれかであり、したがってZipからの素材しか含まれていません。次に:

# list directory in descending order of modification time
$ ls -1t > filelist  # descending order of modification time

次に、テキストエディタでfilelistを開き、Zipからではないリストの最初のエントリを特定します。そのエントリとその後のすべてを削除します。残っているのは、Zipからのファイルとディレクトリです。最初に、名前のスペースのような問題や、エスケープする必要がある引用符の出現を視覚的に検査します。次に、必要に応じて、すべてを引用符で囲みます。以下は、Vimを使用することを前提としています。

:%s/.*/"&"/

次に、すべてを大きな行に結合します。

:%j

次に、その前にrm -rfを挿入します。

Irm - rf<ESC>

カーソルの下の行をシェルコマンドとして実行します。

!!sh<Enter>

間違いなく、私はこのタスクのステップを自動化しませんでした、なぜならそこに既にあったファイルを消すか、ファイル名の問題のために台無しにするリスクがあるからです。

Zip内のパスのリストを取得する明らかなルートをたどる場合は、それをファイルにキャプチャし、非常に注意深く調べ、必要な編集を行った後で削除に変換します。

1
Kaz