Zip todos os arquivos no diretório?


483

Existe uma maneira de compactar todos os arquivos em um determinado diretório com o zipcomando? Já ouvi falar em usar *.*, mas também quero que funcione para arquivos sem extensão.


2
Você já tentou navegar um nível acima do diretório desejado e fazer zip myarch.zip mydir/*?
Joseph R.

13
ou melhorzip -r myarch.zip mydir/*
Adam

25
ou melhorzip -r myarch.zip mydir
ctrl-alt-delor 17/01

*.*significa qualquer arquivo com um ponto. No cp / me no todos os arquivos tinham um ponto, e isso fez você digitá-lo (não pôde *). Portanto, as pessoas passaram a ver *.*como todos os arquivos. Eventualmente, a Microsoft adicionou nomes de arquivos longos que poderiam ter zero ou mais pontos. Para encontrar um arquivo com um ponto no Windows, você deve digitar *.*.*.
Ctrl-alt-delor

Respostas:


705

Você pode apenas usar *; não há necessidade *.*. As extensões de arquivo não são especiais no Unix. *corresponde a zero ou mais caracteres, incluindo um ponto. Portanto, corresponde foo.png, porque são zero ou mais caracteres (sete, para ser exato).

Observe que, *por padrão, não corresponde aos arquivos que começam com um ponto (nem *.*). Isso geralmente é o que você deseja. Caso contrário, no bash, se você shopt -s dotglobquiser (mas ainda excluirá .e ..). Outros shells têm maneiras diferentes (ou nenhuma) de incluir arquivos de ponto.

Como alternativa, ziptambém tem uma -ropção (recursiva) para executar árvores de diretório inteiras de uma só vez (e não precisa se preocupar com o problema do arquivo de pontos):

zip -r myfiles.zip mydir

Onde mydirestá o diretório que contém seus arquivos. Observe que o zip produzido conterá a estrutura de diretórios e os arquivos. Como Peter aponta em seu comentário, isso geralmente é visto como uma coisa boa: a extração do zip armazenará todos os arquivos extraídos em um subdiretório.

Você também pode dizer ao zip para não armazenar os caminhos com a opção -j/ --junk-paths.

O zipcomando vem com documentação informando sobre todas as suas (muitas) opções; digite man zippara ver essa documentação. Isso não é exclusivo do zip; você pode obter documentação para a maioria dos comandos dessa maneira.


9
Você pode adicionar que é considerado uma boa prática conter tudo no arquivo morto em um diretório de nível superior - para que não polua seu diretório atual na extração.
Peterph 28/11/12

@peterph done. Embora isso seja menos uma convenção em arquivos zip do que em tarfiles, receio.
Derobert 28/11/12

Infelizmente sim. Provavelmente devido à herança do drag'n'drop do Windows para a área de trabalho e linux do trabalho com códigos-fonte.
Peterph

2
Lembre-se de que *globbing de shell não inclui arquivos de ponto (por exemplo, nomes de arquivos começando com .). Essa é outra vantagem de compactar o diretório inteiro por nome.
Mrb

Mas usar -r inclui o próprio diretório, que quebra o que estou fazendo. * Não incluiria .e ..?
Tkbx

11

No meu caso, eu queria compactar cada arquivo em seu próprio arquivo, então fiz o seguinte (em zsh):

$ for file in *; do zip ${file%.*}.zip $file; done

1
Não tem mkvaqui? Também nada aqui é particularmente zshespecífico. Você desejará citar adequadamente qualquer variável que contenha um nome de arquivo, portanto, zip "${file%.*}.zip" "$file"entre aspas duplas em torno das duas variáveis.
tripleee

1
@tripleee Em primeiro lugar, obrigado por apontar minha referência errada mkv. Em segundo lugar, citar argumentos é desnecessário zsh, ao contrário de bash. Por isso especifiquei que isso era um comando zsh.
Radon Rosborough

Substituir o último ponto e vírgula por um e comercial pode acelerar significativamente (se o número de arquivos no diretório for razoável ...). Caso contrário find . -type f -maxdepth 1 -print0|xargs -r0 -n1 -P64 -I{} bash -c 'f="{}"; zip "${f%.*}.zip" "$f"'(com -Pajustado dependendo de suas linhas de CPU ...) (muitas dependências GNU ...)
Gert van den Berg

5

Outra maneira seria usar o find e xargs: (isso pode incluir um diretório "." No zip, mas ainda deve ser extraído corretamente. Com o meu teste, o zip retirou o ponto antes da compactação) find . -type f -exec zip zipfile.zip {} +

(Ele +pode ser substituído \;se a sua versão do findnão suportar o +final para o exec. Será mais lento, porém ...)

Por padrão, todos os subdiretórios serão incluídos. No GNU encontrar -maxdepthpode impedir isso.


(ao contrário das soluções usando *, isso vai incluir dotfiles e não vai cair se houver muitos arquivos em um diretório)
Gert van den Berg

1

Outro método (lento) para fazer isso (que adiciona um arquivo ao zip de cada vez):

for f in * .[^.]*; do
    [ -r "$f" ] || continue # Skip directories or non-existant files (Probably ".[^.]*" if directory has no dotfiles). Using -e will allow directories to be used as well
    zip zipfile.zip "$f" # If directories are included, you probably want to add -r
done

Isso tem os problemas do dotfile de *(solução alternativa adicionada) e seria iniciado o zip uma vez para cada arquivo, adicionando-o ao arquivo morto . Em bash, lidaria com uma grande quantidade de arquivos.

Seria mais lento que a maioria dos outros métodos, mas é relativamente simples.


1
Eu diria que isso é menos simples que a resposta aceita e mais lento, o que leva à pergunta: "Por que alguém faria isso?". Se você puder responder a essa pergunta, recomendo que você coloque esse contexto na sua resposta, caso contrário, acho que é uma resposta ruim para uma pergunta antiga que já tem uma boa resposta.
Centimane 17/05/19

@Centimane: observo as limitações. Eu sinto que isso tem valor educacional. (Se não pular diretórios, é bastante simples). Se você deseja uma resposta muito mais rápida usando uma ferramenta externa (padrão), minha outra resposta cobre isso. (com os dotfiles manipulação removido (que afeta a exatidão sem sua ausência mencionado na pergunta), eu sinto que é bastante elegante):for f in *; do zip zip.zip "$f"; done
Gert van den Berg

1
Observe que a resposta aceita não usa um comando externo e seria mais rápida. Em que cenário essa resposta seria útil?
Centimane

@Centimane Com tar quando houver mais arquivos do que o bash pode passar como parâmetros. (encontre + xargs é melhor, pois loops são mais fáceis ...). É uma resposta (única) para a pergunta. Certamente não é a resposta ideal. (Respostas não ideais ainda pode ser útil para problemas semelhantes, se alguém tem uma situação um pouco diferente - arquivo por exemplo tar querendo quaisquer diretórios nele)
Gert van den Berg
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.