web-dev-qa-db-ja.com

tarファイル抽出の混乱を元に戻す

整理されたディレクトリに大量のファイルを作成するアーカイブを解凍しました。例えば:

user@comp:~/tidy$ tar xvf myarchive.tar
file1
file2
dir1/
dir1/file1
dir1/subdir1/
dir1/subdir1/file1
dir2/
dir2/file1
...

私は、tarファイルが単一のフォルダー(つまり、myarchive/)、しかしそうではありませんでした!現在、私には、組織化されたディレクトリであるものにデジタルでバーフィングされた約190のファイルとディレクトリがあります。これらのuntar'dファイルはクリーンアップする必要があります。

これを「元に戻し」、このアーカイブから抽出されたファイルとディレクトリを削除する方法はありますか?


以下の優れた答えをありがとう。 要約、これは2つのステップ(1)ファイルの削除、および(2)空のディレクトリ構造を逆のパッキング順序で削除する(最初に外部ディレクトリを削除する)と機能するものです。

tar tf myarchive.tar | xargs -d'\n' rm
tar tf myarchive.tar | tac | xargs -d'\n' rmdir

さらに安全なのは、echoの後にxargsを追加してコマンドの予行演習をプレビューすることです。

34
Mike T

次のようにtarファイルの内容をリストします。

tar tzf myarchive.tar

次に、そのリストを繰り返して、これらのファイル名を削除します。

while IFS= read -r file; do echo "$file"; done < <(tar tzf myarchive.tar.gz)

これはlist削除されるファイルだけです。これらが削除したいものであることが本当に確かな場合は、echormに置き換えます。そして、確かにバックアップをとってください。

2番目のパスでは、残っているディレクトリを削除します。

while IFS= read -r file; do rmdir "$file"; done < <(tar tzf myarchive.tar.gz)

これにより、が以前に存在していた場合、が削除されないようにします。


@glennjackmanによるもう1つの素晴らしいトリックは、最も深いファイルから順にファイルの順序を維持します。繰り返しますが、完了したらechoを削除します。

tar tvf myarchive.tar | tac | xargs -d'\n' echo rm

その後、通常のrmdirクリーンアップを実行できます。

11
slhck

抽出されたファイルをサブディレクトリに移動して、メインフォルダーをクリーンアップする可能性があります。

    #!/usr/bin/Perl -w

    use strict;
    use Getopt::Long;

    my $clean_folder = "clean";
    my $DRY_RUN;
    die "Usage: $0 [--dry] [--clean=dir-name]\n"
        if ( !GetOptions("dry!" => \$DRY_RUN,
                         "clean=s" => \$clean_folder));

    # Protect the 'clean_folder' string from Shell substitution
    $clean_folder =~ s/'/'\\''/g;

    # Process the "tar tv" listing and output a Shell script.
    print "#!/bin/sh\n" if ( !$DRY_RUN );
    while (<>)
    {
        chomp;

        # Strip out permissions string and the directory entry from the 'tar' list
        my $perms = substr($_, 0, 10);
        my $dirent = substr($_, 48);

        # Drop entries that are in subdirectories
        next if ( $dirent =~ m:/.: );

        # If we're in "dry run" mode, just list the permissions and the directory
        # entries.
        #
        if ( $DRY_RUN )
        {
            print "$perms|$dirent\n";
            next;
        }

        # Emit the Shell code to clean up the folder
        $dirent =~ s/'/'\\''/g;
        print "mv -i '$dirent' '$clean_folder'/.\n";
    }

これをファイルfix-tar.plに保存して、次のように実行します。

$ tar tvf myarchive.tar | Perl fix-tar.pl --dry

これにより、tarリストが私のものであることが確認されます。次のような出力が得られるはずです。

-rw-rw-r--|batch
-rw-rw-r--|book-report.png
-rwx------|CaseReports.png
-rw-rw-r--|caseTree.png
-rw-rw-r--|tree.png
drwxrwxr-x|sample/

それが良さそうであれば、次のようにもう一度実行します。

$ mkdir cleanup
$ tar tvf myarchive.tar | Perl fix-tar.pl --clean=cleanup > fixup.sh

fixup.shスクリプトは、トップレベルのファイルとディレクトリを「クリーンな」フォルダー(この例では、cleanupと呼ばれるフォルダー)に移動するシェルコマンドになります。このスクリプトを調べて、すべてがコーシャであることを確認してください。もしそうなら、今あなたは混乱を片付けることができます:

$ sh fixup.sh

最初のtar xvによって上書きされることによってまだ破棄されていないものは何も破棄しないため、この種のクリーンアップを好みます。

注:最初のドライラン出力が正しくない場合は、2つのsubstr関数呼び出しの数値を適切に見えるまでいじることができるはずです。 $perms変数は予行演習でのみ使用されるため、実際には$direntサブストリングのみが適切である必要があります。

もう1つ:tarリストのユーザー名またはグループ名、あるいはその両方でtarオプション--numeric-ownerを使用すると、名前が予測できない列で始まる場合があります。

2
S2VpdGgA

この種の(反社会的)アーカイブは、その働きからタール爆弾と呼ばれています。これらの1つがあなたに「爆発」したら、他の答えの解決策は、私が提案したものよりもはるかに優れています。

ただし、最善の「解決策」は、最初から問題を回避することです。

これを行う最も簡単な(最も怠惰な)方法は、常に空のディレクトリにtarアーカイブを解凍することです。最上位ディレクトリが含まれている場合は、それを目的の場所に移動するだけです。そうでない場合は、作業ディレクトリ(空のディレクトリ)の名前を変更して、目的の場所に移動します。

初めて正しく取得したい場合は、tar -tvf archive-file.tar |を実行できます。少なくすると、アーカイブの内容が一覧表示されるので、どのように構造化されているかを確認し、最初に目的の場所に抽出するために必要なことを実行できます。

Tオプションは、アーカイブの内容を調べて、探しているものが含まれているかどうかを確認する場合にも便利です。その場合は、必要に応じて、必要なファイルのみを抽出できます。

2
Joe