Remove arquivos com eficiência de grandes .tgz

11

Suponha que eu tenha um arquivo compactadoArchive.tgz compactado com gzip comprimido (+100 arquivos, totalizando + 5gb).

Qual seria a maneira mais rápida de remover todas as entradas que correspondam a um determinado padrão de nome de arquivo, por exemplo, prefixo * .jpg e, em seguida, armazenar os restos em um gzip: ed tar-ball novamente?

Substituir o arquivo antigo ou criar um novo não é importante, o que for mais rápido.

    
por Aksel Willgert 21.06.2013 / 12:07

5 respostas

13

Com o% GNUtar, você pode fazer:

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

com bsdtar :

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

( pigz sendo a versão multi-threaded de gzip ).

Você pode substituir o arquivo como:

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

Mas isso é bastante arriscado, especialmente se o resultado acabar sendo menos compactado que o arquivo original (nesse caso, o segundo pigz pode acabar substituindo áreas do arquivo que o primeiro ainda não leu).

    
por 21.06.2013 / 14:22
7

Não desconte o jeito fácil: ele pode ser rápido o suficiente para o seu propósito. Com avfs para acessar o arquivo como um diretório:

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

Com ferramentas mais primitivas, primeiro extraia os arquivos excluindo os arquivos .jpg , depois crie um novo arquivo.

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

Se seu tar tiver --exclude :

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

Isso pode, no entanto, mangle a propriedade e os modos de arquivo se você não o executar como root. Para obter melhores resultados, use um diretório temporário em um sistema de arquivos rápido - tmpfs, se você tiver um que seja grande o suficiente.

O suporte para que os arquivadores funcionem como uma passagem (isto é, leia um arquivo e grave um arquivo) tende a ser limitado. O GNU tar pode excluir membros de um arquivo com o --delete opção de operação (“A opção --delete foi relatada para funcione corretamente quando tar atuar como um filtro de stdin a stdout . ”) e essa é provavelmente sua melhor opção.

Você pode criar poderosos filtros de arquivo em algumas linhas do Python. Sua biblioteca tarfile pode ler e gravar de fluxos não solicitáveis, e você pode usar código arbitrário em Python para filtrar, renomear, modificar…

#!/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()
    
por 21.06.2013 / 14:46
2

Com o tar que vem no Mac OSX, você pode fazer isso:

tar -czf b.tgz --exclude '*.jpg' @a.tgz
mv b.tgz a.tgz
    
por 02.11.2016 / 22:57
0

Para fazer isso, você provavelmente terá que extrair todo o conteúdo do arquivo .tgz em um diretório local e depois apagar os arquivos que você não deseja, em seguida, recompactar o .tgz.

É longo e você precisa de espaço livre em disco suficiente, mas, de acordo com o meu conhecimento, não há outra maneira de fazê-lo.

Dado que você já tem algum caminho como /tmpdir/withalotofspace que tem espaço livre suficiente (confira usando df -h /tmpdir/withalotofspace ), você pode fazer algo assim:

$ cd /tmpdir/withalotofspace
$ tar -xvfz /path/to/compressedArchive.tgz
$ find /tmpdir/withalotofspace/ -type f -iname '*.jpg' -delete
$ tar -cvzf /path/to/purgedcompressedArchive.tgz .
    
por 21.06.2013 / 14:34
0

Eu gosto da resposta da @Gilles, exceto que ela pode ser ainda mais simplificada. Após a descompactação, por exemplo gunzip foo.tgz , o arquivo será foo.tar e os arquivos poderão ser removidos com tar -f foo.tar --delete file|directory . Abaixo está um exemplo de remoção de um diretório de um arquivo tar.

    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/

Tipos de arquivos específicos podem ser encontrados com tar -tf foo.tar|egrep -i '.jpg$' .

    
por 20.05.2016 / 06:37

Tags