Extração de arquivos .gz contidos em uma pasta


13

Eu tenho uma pasta que contém aproximadamente 320116 arquivos .pdb.gz. Eu quero descomprimir todos eles. Se eu usar o gunzip * .gz, ocorrerá um erro, ou seja, a lista de argumentos é muito longa. A pasta tem cerca de 2 GB. Por favor, me dê uma sugestão apropriada.


Se você precisar trabalhar nessa estrutura de diretórios a longo prazo, divida-o em vários. Por exemplo, com base na hora da modificação dos arquivos ou no nome dos arquivos.
— dan

Sim, eu tenho que trabalhar a longo prazo. eles foram extraídos agora, quero subdividi-los e classificá-los em três pastas com base em seus nomes. Existe um script de shell para fazer isso?
— Lily Sharpton

Eu sugiro que você procure por perguntas semelhantes lá. Se você não encontrar um que atenda às suas necessidades, faça sua própria pergunta.
— dan

Respostas:


26
find . -name '*.pdb.gz' -exec gunzip {} +

-exec gunzip {} +fornecerá gunzipmuitos, mas não muitos, nomes de arquivos em sua linha de comando. Isso é mais eficiente do -exec gunzip {} \;que inicia um novo gunzipprocesso para cada arquivo.


3
Um find, menos gunzip!
— dan

2
Observe que o "+" é um GNUism e, portanto, não funcionará em sistemas não-GNU como * BSD.
— Reintegrar Monica - M. Schröder

3
Versões posteriores do BSD findpermitem a notação "+". Veja, por exemplo, a findpágina de manual do BSD 10.1 . Também se aplica ao OS X (10.9 e posterior, pelo menos, talvez antes).
— plasma

7

Sempre que você receber erros de "lista de argumentos muito longa", poderá contorná-lo invocando o comando desejado várias vezes, sempre com um subconjunto dos argumentos que deseja usar. xargsé uma ferramenta que ajuda você a fazer isso automaticamente.

find . -type f -a -name \*.pdb.gz -print0 | xargs -0 gunzip

isso não tem a mesma ineficiência -execdir gunzip "{}" \;que os xargs invocam o gunzip separadamente para cada arquivo? Essa é a minha leitura da página de manual.
— gogoud

5
Não, xargscolocará quantos nomes de arquivos caberem na gunziplinha de comando. Tente! echo a b c d e f | xargs echoinvoca apenas echouma vez com todos os 6 argumentos, para que você veja uma linha de saída (comando bastante inútil para executar embora !!!!) enquanto que se você forçar xargsa fornecer apenas até 3 argumentos por invocação do comando usando echo a b c d e f | xargs -n 3 echo, obtém 2 linhas de saída .
— Celada

4
Outra vantagem do uso xargsé que, com a -Popção, você pode executar vários gunzipprocessos em paralelo, os quais (dependendo dos parâmetros exatos do seu sistema) podem ser mais rápidos.
— Psmears 19/03/2015

obrigado pelo ponteiro para -P@psmears. Agora eu aprendi algo também!
— Celada

1

Eu acho que isso deve funcionar, ele passa o caminho / nome de cada arquivo individualmente para gunzip para processamento:

find /my/dir -name "*.pdb.gz" -execdir gunzip "{}" \;

1
Isso executará o gunzip uma vez por arquivo. Veja a resposta de John1024 para uma maneira ligeiramente diferente que evita essa ineficiência.
— Celada

@ Celada Isso foi deliberado; minha preocupação era que o uso de + pudesse levar novamente a uma mensagem de erro devido à sobrecarga do gunzip. Se o método de John1024 funcionar, é tecnicamente mais eficiente, mas o meu deve funcionar se o dele não.
— gogoud

1
findcom +e xargssão expressamente projetistas, com exatamente esse problema em mente. Eles sempre fornecerão o maior número possível de argumentos, sem exceder o limite do sistema operacional. Porque, a propósito, é um limite do sistema operacional, nada a ver gunzip.
— Celada

1
@ Celada ok obrigado por essa informação, então presumivelmente com o '+' gunzip pode ser invocado mais de uma vez, mas menos de 320.000 vezes?
— gogoud

1
corrigir.
— Celada

1

Tente desta maneira:

find . -name '*.gz' -exec gunzip {} \;

3
Isso será executado gunzipuma vez por arquivo. Veja a resposta de John1024 para uma maneira ligeiramente diferente que evita essa ineficiência.
— Celada

Certifique-se de escapar do arquivo * in * .gz ... #
— 315751

1

Se você possui uma máquina com vários núcleos, provavelmente verá que esse uso gunzipnão maximizará os recursos da sua máquina. Para isso, você precisaria executar vários gunzips em paralelo. Acompanhar o que é feito em que terminal é manualmente é complicado, mas você pode fazer isso facilmente com o GNU paralelo:

find . -name "*.gz" | parallel -X gunzip {}

1
Isso não irá falhar porque a lista de argumentos parallelé muito longa?
— user253751

@immibis Sim, eu esqueci o problema original, vou atualizar meu post #
— Anthon

Isso ainda não irá falhar porque a lista de argumentos findé muito longa?
— user253751

1
sim, mas você está passando todos os nomes de arquivos na findlinha de comando.
— user253751

Parece que não é um bom dia para responder perguntas, esqueci de citar o argumento para-name
— Anthon

-1

Não é necessário usar findisso, pois você não mencionou subpastas. O que você precisa fazer é:

for f in *.gz;do gunzip $f;done

4
Você não precisa findse você não quer gerar 320116 gunzipprocessos, tal como este laço faz.
— John WH Smith
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.