36 votes

Annuler le désordre de l'extraction d'un fichier tar

Je viens de décompresser une archive qui a produit un désordre de fichiers dans mon répertoire bien rangé. Par exemple :

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

Je m'attendais à ce que le fichier tar soit organisé dans un seul dossier (c'est-à-dire, myarchive/ ), mais ce n'était pas le cas ! J'ai maintenant quelque 190 fichiers et répertoires qui ont dégueulé numériquement dans ce qui était un répertoire organisé. Ces fichiers non tartinés doivent être nettoyés.

Existe-t-il un moyen d'annuler cette opération et de supprimer les fichiers et les répertoires qui ont été extraits de cette archive ?


Merci pour les excellentes réponses ci-dessous. En résumé Voici ce qui fonctionne avec deux étapes (1) supprimer les fichiers, et (2) supprimer la structure de répertoire vide dans l'ordre inverse de l'emballage (pour supprimer les répertoires extérieurs en premier) :

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

Et, ce qui est encore plus sûr, de prévisualiser un essai des commandes en ajoutant echo après xargs .

41voto

Daniel Andersson Points 22765
tar tf archive.tar

énumère le contenu ligne par ligne.

Il peut être acheminé vers xargs directement, mais se méfier La suppression doit être effectuée avec le plus grand soin. Vous ne veulent juste rm -r tout ce qui tar tf vous le dit, car il peut inclure des répertoires qui n'étaient pas vides avant le déballage !

Vous pouvez faire

tar tf archive.tar | xargs -d'\n' rm -v
tar tf archive.tar | sort -r | xargs -d'\n' rmdir -v

pour supprimer d'abord tous les fichiers qui se trouvaient dans l'archive, puis les répertoires restés vides.

sort -r (glennjackman a suggéré tac au lieu de sort -r dans les commentaires de la réponse acceptée, ce qui fonctionne également puisque tar est suffisamment régulier) est nécessaire pour supprimer d'abord les répertoires les plus profonds ; sinon, dans le cas où dir1 contient un seul répertoire vide dir2 quittera dir1 après la rmdir de passer, puisqu'il s'agit de no vide avant dir2 a été supprimée.

Cela générera un grand nombre de

rm: cannot remove `dir/': Is a directory

y

rmdir: failed to remove `dir/': Directory not empty
rmdir: failed to remove `file': Not a directory

Faites-le taire avec 2>/dev/null si cela vous ennuie, mais je préfère garder autant d'informations que possible sur le processus.

Et ne le faites pas avant d'être sûr de correspondre aux bons fichiers. Et essayez peut-être rm -i pour tout confirmer. Et ayez des sauvegardes, prenez votre petit-déjeuner, brossez-vous les dents, etc.

13voto

slhck Points 209720

Listez le contenu du fichier tar comme suit :

tar tzf myarchive.tar

Supprimez ensuite ces noms de fichiers en parcourant cette liste :

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

Il s'agira toujours d'un liste les fichiers qui seront supprimés. Remplacer echo con rm si vous êtes vraiment sûr que ce sont ceux que vous voulez supprimer. Faites éventuellement une sauvegarde pour vous en assurer.

Dans un deuxième temps, supprimez les répertoires restants :

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

Cela permet d'éviter que les répertoires avec soient supprimés s'ils existaient déjà auparavant.


Une autre astuce de @glennjackman, qui préserve l'ordre des fichiers, en commençant par les plus profonds. Encore une fois, enlevez echo une fois l'opération terminée.

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

Cette étape pourrait être suivie de la procédure normale rmdir nettoyage.

2voto

S2VpdGgA Points 91

Voici une possibilité qui prendra les fichiers extraits et les déplacera dans un sous-répertoire, nettoyant ainsi votre dossier principal.

    #!/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";
    }

Enregistrez ceci dans le fichier fix-tar.pl et l'exécuter comme suit :

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

Cela confirmera que votre tar est comme la mienne. Vous devriez obtenir des résultats comme :

-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/

Si cela semble correct, relancez l'opération de la manière suivante :

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

En fixup.sh Les script seront les commandes script qui déplaceront les fichiers et répertoires de premier niveau dans un dossier "propre" (dans ce cas, le dossier appelé cleanup ). Jetez un coup d'œil à ce script pour confirmer que tout est kasher. Si c'est le cas, vous pouvez maintenant nettoyer le désordre avec :

$ sh fixup.sh

Je préfère ce type de nettoyage parce qu'il ne détruit rien qui ne soit déjà détruit par l'écrasement de ce fichier initial. tar xv .

Remarque : si le résultat de la première simulation n'est pas satisfaisant, il est possible de modifier les chiffres dans les deux champs de saisie. substr jusqu'à ce qu'ils soient corrects. Les $perms n'est utilisée que pour la marche à blanc, de sorte que seule la variable $dirent doit être correcte.

Autre chose : il se peut que vous ayez besoin d'utiliser la fonction tar option --numeric-owner si les noms d'utilisateurs et/ou de groupes dans le tar l'énumération fait commencer les noms dans une colonne imprévisible.

2voto

Eigir Points 471

Ce type d'archive (antisociale) est appelé "bombe à goudron" en raison de ses effets. Une fois que l'une d'entre elles vous a "explosé", les solutions proposées dans les autres réponses sont bien meilleures que celles que j'aurais suggérées.

La meilleure "solution" consiste toutefois à prévenir le problème dès le départ.

La façon la plus simple (et la plus paresseuse) de procéder est de toujours décompresser une archive tar dans un répertoire vide. Si elle contient un répertoire de premier niveau, il suffit de le déplacer vers la destination souhaitée. Sinon, il suffit de renommer votre répertoire de travail (celui qui était vide) et de le déplacer vers l'emplacement souhaité.

Si vous voulez faire les choses correctement du premier coup, vous pouvez lancer tar -tvf archive-file.tar | less et il listera le contenu de l'archive afin que vous puissiez voir comment elle est structurée et faire le nécessaire pour l'extraire à l'endroit désiré pour commencer.

L'option t est également très utile si vous souhaitez inspecter le contenu d'une archive pour voir si elle contient quelque chose que vous recherchez. Si c'est le cas, vous pouvez, en option, extraire le(s) fichier(s) désiré(s).

0voto

张诗正 Points 1
tar -tf fly.tar | cut -d"/" -f1 | uniq | xargs rm -rf

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X