Como zipar vários arquivos na linha de comando?

16

Perdoe essa pergunta mais básica, mas não consegui encontrar uma resposta direta ou um exemplo simples sobre troca de pilhas.

Digamos que eu tenho uma pasta de arquivos que gostaria de compactar em um arquivo zip que eu possa compartilhar com meus terríveis amigos do Windows (caso contrário, eu apenas usaria tare terminaria). Se parece com isso:

.
├── file1.txt
├── file2.txt
├── file3.txt
├── file.jpg
└── test.jpg

Supondo que eu zipinstalei:

sudo apt-get install zip

Vejo man zipque isso me permite usar uma lista de arquivos:

- @ listas de arquivos. Se uma lista de arquivos for especificada como - @ [Não no MacOS], o zip utilizará a lista de arquivos de entrada da entrada padrão em vez da linha de comando. Por exemplo,

          zip -@ foo

Então eu criei o zip.lstseguinte:

cat zip.lst

file1.txt
file2.txt
file3.txt
file.jpg
test.jpg

E agora eu tentei:

zip -@ zip.lst

Mas não fez nada, exceto criar uma linha em branco no console. E eu posso continuar pressionando Entere ele continua criando mais linhas em branco sem aparentemente executar o comando. Após algumas pesquisas, percebi que precisava finalizar a entrada pressionando Ctrl+D

Mas agora eu recebo este erro:

    zip warning: missing end signature--probably not a zip file (did you
    zip warning: remember to use binary mode when you transferred it?)
    zip warning: (if you are trying to read a damaged archive try -F)

zip error: Zip file structure invalid (zip.lst)

O que!? Como minha lista simples não é uma "estrutura de arquivo válida"? Volte ao manual para obter mais informações e examinarei mais de perto:

Se uma lista de arquivos for especificada como - @ ...

Então, eu tento sem -@, e isso pelo menos processa-o imediatamente, sem ter que pressionar Ctrl+, Dmas fiquei com o mesmo erro .

Felizmente, encontrei um comentário em uma resposta a uma pergunta quase não relacionada que me levou a perceber que precisava nomear explicitamente o arquivo zip. Este erro ocorreu porque, por padrão, ele estava tentando criar um arquivo zip chamado zip.lst. Mas como esse é o nome da minha lista, pode-se pensar que simplesmente a substituirá, mas não, estava de fato tentando atualizá-la. E como a lista obviamente não é um arquivo zip, obtemos o erro de estrutura de arquivo inválido e agora está claro por que disse "provavelmente não é um arquivo zip". Então eu tentei:

zip files.zip zip.lst

adding: zip.lst (deflated 35%)

Eureka! Eu posso ver que o arquivo zip foi criado e minha pasta agora contém isso:

.
├── file1.txt
├── file2.txt
├── file3.txt
├── file.jpg
├── files.zip
├── test.jpg
└── zip.lst

Mas espere antes de comemorarmos, vamos confirmar o conteúdo do arquivo zip primeiro:

unzip -l files.zip

Archive:  files.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
       48  2016-05-24 15:30   zip.lst
---------                     -------
       48                     1 file

Não! Bem, na verdade isso faz sentido com o uso padrão, porque apenas compactou o arquivo de lista que eu dei. Finalmente tentei novamente com, -@mas obtive o mesmo resultado.

O que estou fazendo de errado?

BTW, eu sei que posso usar a GUI e fazê-lo com o mouse, mas preciso criar um script e, em geral, sou mais rápido na CLI quando sei o que estou fazendo.

Jeff Puckett
fonte

Respostas:

23

Usar <redirecionamento de arquivo

zip files.zip -@ < zip.lst

Ou você pode pular a lista e apenas glob

zip files.zip *.txt *.jpg

obrigado steeldriver

Resposta Histórica

Fico feliz que não há problema em responder à minha própria pergunta, porque eu queria narrar meu tumulto na esperança de que outros que estão seguindo o meu rastro de lágrimas pudessem ser poupados pesquisando algumas palavras-chave.

Eventualmente, descobri a resposta certa , mas ela foi postada na pergunta errada .

Alguns pontos de clareza:

  • O manual não se refere a uma lista literal como em um arquivo, mas literalmente a listar os arquivos no console.
  • É compreensível que alguém possa ser enganado ao pensar que se foorefere à lista de arquivos, mas na verdade pretende representar o nome do arquivo zip de saída.
  • A lista de arquivos é omitida no exemplo porque está usando a -@opção, que demonstra que "pega a lista de arquivos de entrada da entrada padrão em vez da linha de comando "

Entendendo isso, agora estamos armados com várias maneiras de atingir o objetivo.

Primeiramente, usando a lista de arquivos que criamos, podemos ler a lista cate redirecionar a saída com um pipe como entrada padrão para compactar:

cat zip.lst | zip -@ files.zip

  adding: file1.txt (stored 0%)
  adding: file2.txt (stored 0%)
  adding: file3.txt (stored 0%)
  adding: file.jpg (stored 0%)
  adding: test.jpg (stored 0%)

Ver que adding: ...para cada arquivo é certamente um bom sinal, mas já tínhamos esperanças antes, então vamos confirmar:

unzip -l files.zip

Archive:  files.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2016-05-24 14:54   file1.txt
        0  2016-05-24 14:54   file2.txt
        0  2016-05-24 14:54   file3.txt
        0  2016-05-24 15:00   file.jpg
        0  2016-05-24 14:59   test.jpg
---------                     -------
        0                     5 files

DOCE! Mas quem quer criar uma lista de uso único de qualquer maneira? Essa é uma maneira terrível de solucionar esse cenário em particular. Seria melhor obter uma lista lse canalizá-la para zip:

ls | zip -@ files.zip

  adding: file1.txt (stored 0%)
  adding: file2.txt (stored 0%)
  adding: file3.txt (stored 0%)
  adding: file.jpg (stored 0%)
  adding: test.jpg (stored 0%)

Fabuloso! Agora vamos criar filtros com o incrível poder de grepcompactar apenas os jpgs, por exemplo:

ls | grep .jpg | zip -@ images.zip

  adding: file.jpg (stored 0%)
  adding: test.jpg (stored 0%)

Ou apenas arquivos começando com "arquivo"

ls | grep file. | zip -@ files.zip

  adding: file1.txt (stored 0%)
  adding: file2.txt (stored 0%)
  adding: file3.txt (stored 0%)
  adding: file.jpg (stored 0%)
Jeff Puckett
fonte
5
Em vez de usar lse grepe zip de -@, você pode usar globs shell para selecionar arquivos diretamente na linha de comando zip por exemplo, zip files.zip file*ou zip images.zip *.jpg. Além disso, quando se utiliza uma lista de nomes de arquivos a partir de um arquivo, você pode usar o redirecionamento em vez de chamar um processo gato separado,zip files.zip -@ < zip.lst
steeldriver
Como você pode fazer isso funcionar com diretórios aninhados ao lado de arquivos?
BallpointBen
@BallpointBen eu usaria em findvez dels
Jeff Puckett
6

o comando mais simples com nível máximo de compactação

zip -9 -r filename.zip /path/to/dir singlefile.jpg 
Ansyori
fonte