解凍、tar -xvfを解凍する方法-乱雑なフォルダーで解凍しますか?


14

通常、私は物事をアーカイブ解除します$ mkdir newFolder; $ mv *.zip newFolder; $ cd newFolder; $unzip *.zipが、時々怠け者になり$ unzip *.zip、他のコンテンツを時々めちゃくちゃにするために、任意のフォルダで実行します。ここにいくつかの方法をリストします-いくつかのアーカイブバージョンは確かにクラッピーフラグを持っていますが、他のバージョンはより質素で、後者についてもっと興味があります。

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

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

  2. 少量の抽出ファイルの場合、1つずつ、遅く、扱いにくく、エラーが発生しやすくなります。

  3. archieveのコンテンツが実際にフォルダーであるかどうかを確認したいときは$ unzip -l *.bsd、少なくともobsdのunzipバージョンで動作することを時々確認します。

特定のアーカイブツールについて言及している場合は、必要に応じてそれらを明記してください。シンプルに保ちましょう-単一のツールではなく、あなたのやり方にもっと興味があります。



以下は、mkdir; unzipものを自動化するために使用するスクリプトです。 svn.mikelward.com/svn/scripts/untar
ミケル

2
この関連の質問と回答を参照してください。unix.stackexchange.com/questions/5123/...
アレックス・

回答:


11

名前で

アーカイブ内のファイルのリストを生成して削除できますが、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を使用して、通常のファイルシステムコマンドを使用してアーカイブを操作できます。

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。完全に除外できます。zshまたはfind; を使用したコマンドの例を次に示します。-cminおよび-cnewerprimariesは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を使用して、必要に応じて宛先にディレクトリを作成する方法を示します。

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なければ)。


今日、ようやくこの問題に遭遇しました。ルートとして!最後に、「名前」と「日付」の組み合わせを使用しました
プネヘヘ

1

とにかく、同じような問題が発生したときにこのスクリプトを書くために頭を掻いた。ファイルのリストを取得するcpioために-itフラグを使用しました。他のアーカイバに対して同等のコマンドを使用できます。トリッキーな部分は、cpioアーカイブはinitrdからのものであり、私はに抽出した/ため、多くのフォルダーとファイルは動作中のシステムと同じ名前を持っています。幸いにも、cpioは既存のファイルを上書きしませんでした。時間チェックを使用して、間違ったコマンドの前に存在していたものを削除しないようにします。

#! /bin/sh

files=$(cpio -it < /mnt/temp/lglive.cpio)

for i in ${files}
do
    name=$(stat -c "%n" ${i})
    time=$(stat -c "%Y" ${i})
    # Time of the creation of the mess: 1296457595
    if [[ ${time} -gt 1296457590 && ${time} -lt 1296457600 ]]
    then
        if [[ -f ${name} ]]
        # If it is a file, it must have been created as part of the mess.
        then
            echo "rm ${name}"
        elif [[ -d ${name} ]]
        # If it is a directory, it may have been part of the mess
        # or maybe some files underneath it is created as part of the mess.
        then
            if [[ $(ls -A ${name}) ]]
            # If the directory contains something then don't delete it.
            then
                echo "${name} is not empty"
            # If the directory is empty then assume it is rubbish.
            else
                echo "rmdir ${name}"
            fi
        fi
    fi
done

echo "Files and directories still exist after the removal:"
for i in ${files}
do
    if [[ -e ${i} ]]
    then
        echo ${i}
    fi
done

0

アーカイブ内のファイルのリストをフィードするのはどうxargs rmですか?

それは次のようになりますtar -tf tarbomb.tar | xargs rmunzip --list zipbomb.zip | xargs rm


2
与えられたコマンドは一般的なケースでは機能せず、ファイルを削除するのでこれは危険です。xargs入力が生成されfindない特異な方法で引用されていることを期待します。xargs -I rm {}代わりに、xargsが行ごとに1つのアイテムを処理するように使用します。unzipコマンドの場合、どのような実装がありますか?Mine(Debian / Ubuntu)には--list、のみがなく-l、ファイル名を出力するだけではないため、追加の処理が必要です。
ジル 'SO-悪であるのをやめる'

@Gilles:1)はい、それは危険ですが、おそらく元のファイルを上書きしているので、すでになくなっています。2)私は話していませんでしたfind。3)あなたはについて正しいですunzip、私はテストしませんでした、そして、装飾されていないリストのためのオプションがないようです。ノー--list私のUbuntuの上だけでなく-私はテストしませんでした。
アレックス

申し訳ありませんが缶詰応答について、代替tar -tのためにfind。しかし、他のポイントは立っています。与えられたコマンドが無関係なファイルを削除するという本当のリスクがあります。
ジル 'SO-悪であるのをやめる'

tar -tf tarbomb.tarファイル名を1行に1つずつ出力するためtar -tf tarbomb.tar | while IFS=$'\n' read -r filename; do rm "$filename"; done、同様のことができます。
ミケル

0

本当にあなたが求めたものではありませんが、代わりに「すべてを解凍」スクリプトを使用する方法はどうでしょう。

unzip *.zip

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

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

0

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

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

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.