Existe uma maneira de compactar todos os arquivos em um determinado diretório com o comando zip
? Já ouvi falar do uso de *.*
, mas também quero que funcione para arquivos sem extensão.
Comentários
Resposta
Você pode apenas usar *
; não há necessidade para *.*
. As extensões de arquivo não são especiais no Unix. *
corresponde a zero ou mais ch caracteres – incluindo um ponto. Portanto, corresponde a foo.png
, porque é zero ou mais caracteres (sete, para ser exato).
Observe que *
por padrão não corresponde a arquivos que começam com um ponto (nem *.*
). Geralmente é isso que você deseja. Do contrário, no bash, se você shopt -s dotglob
irá (mas ainda excluirá .
e ..
). Outros shells têm maneiras diferentes (ou nenhuma) de incluir dotfiles.
Como alternativa, zip
também tem um -r
opção (recursiva) para fazer árvores de diretório inteiras de uma vez (e não precisa se preocupar com o problema do dotfile):
zip -r myfiles.zip mydir
where mydir
é o diretório que contém seus arquivos. Observe que o zip produzido conterá a estrutura do diretório, bem como os arquivos. Como peterph aponta em seu comentário, isso geralmente é visto como uma coisa boa: extrair o zip irá armazenar ordenadamente todos os arquivos extraídos em um subdiretório.
Você também pode dizer ao zip para não armazenar os caminhos com o opção -j
/ --junk-paths
.
O comando zip
vem com documentação informando sobre todas as suas (muitas) opções; digite man zip
para ver essa documentação. Isso não é exclusivo do zip; você pode obter documentação para a maioria dos comandos desta forma.
Comentários
- Você pode querer adicionar, que é considerado uma boa prática conter tudo no arquivo em um diretório de nível superior – para que não ‘ polua seu diretório atual na extração.
- @peterph done. Embora isso seja menos uma convenção em arquivos zip do que em tarfiles, ‘ estou com medo.
- infelizmente sim. Provavelmente devido às janelas herança de arrastar ‘ n ‘ soltar na área de trabalho e herança do Linux de trabalhar com códigos-fonte.
- Mantenha-se atento lembre-se de que
*
shell-globbing não ‘ inclui dotfiles (ou seja, nomes de arquivos começando com.
). Esta é outra vantagem de compactar todo o diretório por nome. - Mas usar -r inclui o próprio diretório, o que quebra o que eu ‘ estou fazendo. Não ‘ * incluiria
.
e..
?
Resposta
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
Comentários
- Existem ‘ s não
mkv
aqui? Além disso, nada aqui é particularmentezsh
específico. Você ‘ desejará citar adequadamente qualquer variável que contenha um nome de arquivo, entãozip "${file%.*}.zip" "$file"
com aspas duplas em torno de ambas as variáveis. - @tripleee Em primeiro lugar, obrigado por apontar minha referência errada a
mkv
. Em segundo lugar, citar argumentos é desnecessário emzsh
, ao contrário debash
. É ‘ por isso que especifiquei que este era um comando parazsh
. - Substituindo 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-P
ajustado dependendo de seus threads de CPU …) (Muitas dependências GNU …) - para compactar cada arquivo em seu próprio arquivo,
gzip *
Resposta
Outra maneira seria usar find e xargs: (isso pode incluir um diretório “.” no zip, mas ainda deve extrair corretamente. Com meu teste, o zip removeu o ponto antes compressão) find . -type f -exec zip zipfile.zip {} +
(O +
pode ser substituído por \;
se sua versão de find
não for compatível com o +
final para exec. Porém, será mais lento …)
Por padrão, isso incluirá todos os subdiretórios. No GNU, encontre -maxdepth
pode evitar isso.
Comentários
- (ao contrário das soluções que usam
*
, isso incluirá dotfiles e não ‘ cairá se houver muitos arquivos em um diretório)
Resposta
Outro método (lento) para fazer isso (que adiciona um arquivo ao zip por 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 de dotfile de *
(solução alternativa adicionada) e seria iniciar zip uma vez para cada arquivo, adicionando-o ao arquivo. Em bash
, ele lidaria com uma grande quantidade de arquivos.
Seria mais lento do que a maioria dos outros métodos, mas é relativamente simples.
Comentários
- Eu diria que é menos simples do que a resposta aceita e mais lenta, o que leva à pergunta: ” Por que alguém faria isso? “. Se você puder responder a essa pergunta, recomendo que coloque esse contexto em sua resposta, caso contrário, acho que é uma resposta ruim para uma pergunta antiga que já tem uma boa resposta.
- @Centimane: Eu noto as limitações . Eu sinto que isso tem valor educacional. (Se não estiver pulando diretórios, é bastante simples). Se você quiser uma resposta muito mais rápida usando uma ferramenta externa (padrão), minha outra resposta cobre isso. (com o manuseio de dotfiles removido (o que afeta a correção sem sua ausência mencionada na pergunta), acho que é bastante elegante):
for f in *; do zip zip.zip "$f"; done
- Observe que o aceito A resposta não ‘ não usa um comando externo e seria mais rápida. Em que cenário esta resposta seria útil?
- @Centimane Com tar quando há mais arquivos do que o bash pode passar como parâmetros. (find + xargs são melhores, pois loops são mais fáceis …). É uma resposta (única) à pergunta. Certamente não é a resposta ideal. (Respostas não ótimas ainda podem ser úteis para problemas semelhantes, se alguém tiver uma situação ligeiramente diferente – por exemplo, querer o arquivo tar em qualquer diretório nele)
zip myarch.zip mydir/*
?zip -r myarch.zip mydir/*
zip -r myarch.zip mydir
*.*
significa qualquer arquivo com um ponto. Em cp / m e dos todos os arquivos tinham um ponto, e isso obrigou você a digitá-lo (não foi possível*
). Portanto, as pessoas vieram ver*.*
como todos os arquivos. Eventualmente, a Microsoft adicionou nomes de arquivo longos que podem ter zero ou mais pontos. Para encontrar um arquivo com um ponto nas janelas, você deve digitar*.*.*
.