Como criar um zip com vários arquivos sem subpastas?

12

Situação inicial:

.
├── d0
├── f0
├── f1
│   └── d1
└── f2
    └── f3
        ├── d2
        ├── d3
        └── d4

O que eu preciso fazer:

Gostaria de criar um zip contendo d0, d1 e d4, que deve ter a seguinte estrutura:

.
├── d0
├── d1
└── d4

O que eu já tentei:

Eu tentei com isso zip myfiles d0 f1/d1 f2/f3/d4. Mas isso mantém a estrutura da pasta original, que não é o que eu quero.

.
├── d0
├── f1
│   └── d1
└── f2
    └── f3
        └── d4

Pergunta Como criar um zip com vários arquivos sem as subpastas?

eDeviser
fonte

Respostas:

17

Manualmente, você pode criar o arquivo zip e atualizá-lo:

zip myfiles d0
(cd f1; zip -u ../myfiles.zip d1)
(cd f2/f3; zip -u ../../myfiles.zip d4)

Os parênteses criam subcascas, e o efeito da cdúnica dura na subcasca, para que você não precise cdvoltar ao diretório original.

Se d1, d2etc. são realmente arquivos e não diretórios, use a -jopção:

-j
--junk-caminhos
Armazena apenas o nome de um arquivo salvo (lixo eletrônico o caminho) e não armazena nomes de diretório. Por padrão, o zip armazenará o caminho completo (relativo ao diretório atual).

muru
fonte
19

Você pode usar findpara obter a lista de arquivos e executar zip -j myfilespara compactá-los, ignorando os caminhos:

find . -name "d[014]" -exec zip -j myfiles {} +

Exemplo

$ tree
.
├── d0
├── f0
├── f1
│   └── d1
└── f2
    └── f3
        ├── d2
        ├── d3
        └── d4

$ find . -name "d[014]" -exec zip -j myfiles {} +
  adding: d1 (stored 0%)
  adding: d4 (stored 0%)
  adding: d0 (stored 0%)

$ unzip -l myfiles.zip
Archive:  myfiles.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2017-10-09 10:47   d1
        0  2017-10-09 10:48   d4
        0  2017-10-09 10:47   d0
---------                     -------
        0                     3 files

No entanto, isso funciona apenas para arquivos , os diretórios serão ignorados por zip -j. Para que isso funcione também para diretórios, digamos que queremos compactar d0, d1e todo o f3diretório no exemplo acima, a findlinha fica um pouco mais complicada:

$ find . \( -name "d[01]" -o -name "f3" \) -exec sh -c 'p=$(pwd); for i in $0 $@; do cd ${i%/*}; zip -ur "$p"/myfiles ${i##*/}; cd "$p"; done' {} +
        zip warning: /home/dessert/myfiles.zip not found or empty
  adding: d1 (stored 0%)
  adding: f3/ (stored 0%)
  adding: f3/d3 (stored 0%)
  adding: f3/d2 (stored 0%)
  adding: f3/d4 (stored 0%)
  adding: d0 (stored 0%)
$ unzip -l myfiles.zip 
Archive:  myfiles.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2017-10-11 10:18   d1
        0  2017-10-11 10:19   f3/
        0  2017-10-11 10:19   f3/d3
        0  2017-10-11 10:19   f3/d2
        0  2017-10-11 10:19   f3/d4
        0  2017-10-11 10:17   d0
---------                     -------
        0                     6 files
sobremesa
fonte
18

O uso da opção -j removerá o caminho do arquivo.

zip -j myfiles d0 f1/d1 f2/f3/d4 

referência

ravery
fonte
se algum dos caminhos que você está passando não são arquivos, mas diretórios, esses diretórios não serão adicionados ao ziparquivo com a -jopção
Dan
@ Dan --se você quer todos os arquivos em um diretório com o caminho entãozip -j myfiles directory/*
Ravery