web-dev-qa-db-fra.com

Supprimer efficacement le (s) fichier (s) de grand .tgz)

Supposons que j'ai un gzip compressé tar-ball compressedArchive.tgz (+100 fichiers, totalisant + 5 Go).

Quel serait le moyen le plus rapide de supprimer toutes les entrées correspondant à un modèle de nom de fichier donné par exemple préfixe * .jpg, puis stockez les restes dans une gzip: éd tag-ballon à nouveau?

Remplacer l'ancienne archive ou la création d'un nouveau n'est pas important, selon la première éventualité la plus rapide.

14
Aksel Willgert

Avec GNU tar, vous pouvez faire:

pigz -d < file.tgz |
  tar --delete --wildcards -f - '*/prefix*.jpg' |
  pigz > newfile.tgz

Avec bsdtar:

pigz -d < file.tgz |
  bsdtar -cf - --exclude='*/prefix*.jpg' @- |
  pigz > newfile.tgz

(pigz étant la version multi-threadée de gzip).

Vous pouvez écraser le fichier sur lui-même comme:

{ pigz -d < file.tgz |
    tar --delete --wildcards -f - '*/prefix*.jpg' |
    pigz &&
    Perl -e 'truncate STDOUT, tell STDOUT'
} 1<> file.tgz

Mais c'est assez risqué, surtout si le résultat finit par être moins compressé que le fichier d'origine (auquel cas, le deuxième pigz peut finir par écraser les zones d'écrasement du fichier que le premier n'a pas encore lu).

14
Stéphane Chazelas

Ne négligez pas le moyen facile: il peut être assez rapide pour votre but. Avec AVFS Pour accéder à l'archive en tant que répertoire:

cd ~/.avfs/path/to/original.tar.gz\#
pax -w -s '/^.*\.jpg$//' | gzip >/path/to/filtered.tar.gz        # POSIX
tar -czf /path/to/filtered.tar.gz -s '/^.*\.jpg$//' .            # BSD
tar -czf /path/to/filtered.tar.gz --transform '/^.*\.jpg$//' .   # GNU

Avec des outils plus primitifs, extrait d'abord les fichiers à l'exclusion de l'.jpg Fichiers, puis créez une nouvelle archive.

mkdir tmpdir && cd tmpdir
<original.tar.gz gzip -d | pax -r -pe -s '/^.*\.jpg$//'
pax -w . | gzip >filtered.tar.gz
cd .. && rm -rf tmpdir

Si votre goudron a --exclude:

mkdir tmpdir && cd tmpdir
tar -xzf original.tar.gz --exclude='*.jpg'
tar -czf filtered.tar.gz .
cd .. && rm -rf tmpdir

Cela peut toutefois mangler la propriété et les modes de fichiers si vous ne l'exécutez pas en tant que root. Pour de meilleurs résultats, utilisez un répertoire temporaire sur un système de fichiers rapide - TMPFS si vous en avez une assez grande.

Soutien aux archiveurs d'agir comme une passage (c'est-à-dire une archive et écrire une archive) a tendance à être limitée. GNU TAR peut supprimer des membres d'une archive avec le --delete option de fonctionnement ("The --delete L'option a été signalée correctement lorsque tar agit en tant que filtre de stdin à stdout. "), et c'est probablement votre meilleure option.

Vous pouvez faire de puissants filtres d'archives dans quelques lignes de python. Son tarfile Bibliothèque peut lire et écrire à partir de flux non recherchables, et vous pouvez utiliser le code arbitraire dans Python pour filtrer, renommer, modifier, modifier ...

#!/usr/bin/python
import re, sys, tarfile
source = tarfile.open(fileobj=sys.stdin, mode='r|*')
dest = tarfile.open(fileobj=sys.stdout, mode='w|gz')
for member in source:
    if not (member.isreg() and re.match(r'.*\.jpg\Z', member.name)):
        sys.stderr.write(member.name + '\n')
        dest.addfile(member, source.extractfile(member))
dest.close()

Pour ce faire, vous devez probablement extraire tout la contenante du fichier .tgz dans un dir local puis effacez les fichiers que vous ne souhaitez pas, puis recompretez le .tgz.

C'est long et vous avez besoin de suffisamment d'espace disque gratuit, mais au meilleur de ma connaissance, il n'y a pas d'autre moyen de le faire.

Étant donné que vous avez déjà un chemin comme /tmpdir/withalotofspace qui ont un espace libre suffisant (vérifiez-le en utilisant df -h /tmpdir/withalotofspace), tu peux faire quelque chose comme ça:

$ cd /tmpdir/withalotofspace
$ tar -xvfz /path/to/compressedArchive.tgz
$ find /tmpdir/withalotofspace/ -type f -iname '*.jpg' -delete
$ tar -cvzf /path/to/purgedcompressedArchive.tgz .
1
DavAlPi

J'aime la réponse de @gilles, sauf que cela peut être encore simplifié. Après avoir décompressé, par exemple gunzip foo.tgz le fichier sera foo.tar et les fichiers peuvent être supprimés avec tar -f foo.tar --delete file|directory. Vous trouverez ci-dessous un exemple d'élimination d'un répertoire à partir d'un fichier de goudron.

    phablet@ubuntu-phablet:~/Downloads$ tar -cvf moo.tar moo1/
    moo1/
    moo1/moo2/
    moo1/moo2/moo3/
    moo1/moo2/moo3/moo4/
    moo1/moo2/moo3/moo4/moo5/
    phablet@ubuntu-phablet:~/Downloads$ tar -tf moo.tar 
    moo1/
    moo1/moo2/
    moo1/moo2/moo3/
    moo1/moo2/moo3/moo4/
    moo1/moo2/moo3/moo4/moo5/
    phablet@ubuntu-phablet:~/Downloads$ tar -f moo.tar --delete "moo1/moo2/moo3"
    phablet@ubuntu-phablet:~/Downloads$ tar -tf moo.tar 
    moo1/
    moo1/moo2/

Les types de fichiers spécifiques peuvent être trouvés avec tar -tf foo.tar|egrep -i '.jpg$'.

0
Funmungus

J'utilise:

tar -xvf myLarge.gz --exclude "prefix" | tar -czvf myLarge.gz -T -

Cette volonté:

  1. Extraire tous les fichiers sauf les fichiers, y compris "préfixe"
  2. (-T -) Tuyau repose au goudron et re-compresse mylarge.gz
0
Cyborg