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.

Lily Sharpton
fonte
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.

John1024
fonte
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
Celada
fonte
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 "{}" \;
gogoud
fonte
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 {} \;
jherran
fonte
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 {}
Anthon
fonte
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
Tolga Ozses
fonte
4
Você não precisa findse você não quer gerar 320116 gunzipprocessos, tal como este laço faz.
John WH Smith