Como compactar todos os arquivos de várias subpastas?

5

Entrada bruta:

    ➜  test tree
    .
    ├── f1.md
    ├── f2.md
    ├── f3.md
    ├── f4.txt
    ├── f5.csv
    ├── f6.doc
    ├── s1
    │   ├── code
    │   └── data
    │       ├── f1.md
    │       ├── f2.md
    │       ├── f3.md
    │       ├── f4.txt
    │       ├── f5.csv
    │       └── f6.doc
    ├── s2
    │   ├── code
    │   └── data
    │       ├── f1.md
    │       ├── f2.md
    │       ├── f3.md
    │       ├── f4.txt
    │       ├── f5.csv
    │       └── f6.doc
    ├── s3
    │   ├── code
    │   └── data
    │       ├── f1.md
    │       ├── f2.md
    │       ├── f3.md
    │       ├── f4.txt
    │       ├── f5.csv
    │       └── f6.doc
    └── s4
        ├── code
        └── data
            ├── f1.md
            ├── f2.md
            ├── f3.md
            ├── f4.txt
            ├── f5.csv
            └── f6.doc

    12 directories, 30 files

Saída esperada

➜  test tree
.
├── f1.md
├── f2.md
├── f3.md
├── f4.txt
├── f5.csv
├── f6.doc
├── s1
│   ├── code
│   └── data
│       ├── Archive.zip
│       ├── f1.md
│       ├── f2.md
│       ├── f3.md
│       ├── f4.txt
│       ├── f5.csv
│       └── f6.doc
├── s2
│   ├── code
│   └── data
│       ├── Archive.zip
│       ├── f1.md
│       ├── f2.md
│       ├── f3.md
│       ├── f4.txt
│       ├── f5.csv
│       └── f6.doc
├── s3
│   ├── code
│   └── data
│       ├── f1.md
│       ├── f2.md
│       ├── f3.md
│       ├── f4.txt
│       ├── f5.csv
│       └── f6.doc
└── s4
    ├── code
    └── data
        ├── Archive.zip
        ├── f1.md
        ├── f2.md
        ├── f3.md
        ├── f4.txt
        ├── f5.csv
        └── f6.doc

12 directories, 33 files

Eu quero arquivos de subpastas (s1 / s2 / s4) para compactar.

Eu tentei usar a linha de comando zip -r Archive.zip ./* em cada subpasta (s1 / s2 / s4). É inconveniente porque tenho que digitar os mesmos comandos por três vezes.

Como eu uso um comando uma vez ou escrevo um script para conseguir isso? Eu estou no OSX (10.12.6).

    
por Jack 25.08.2017 / 09:10

3 respostas

3

Algo parecido com este script pode fazer o trabalho:

for i in 'find /path -type d -name data';
do
if [ "$i" = "s3/data" ]
 then continue
 else cd "$i" && zip Archive.zip *
fi
done

P.S. Substitua /path pelo ponto inicial da sua árvore de diretórios

    
por 25.08.2017 / 09:18
5
find . -type d -name data -execdir zip -jr data/Archive.zip data ';'

Este comando find encontrará cada diretório data sob o diretório atual e executará

zip -jr data/Archive.zip data

em cada um dos diretórios sN (o diretório pai dos diretórios data ). Isso também irá arquivar arquivos ocultos.

O -j flag para zip removerá os nomes de caminho dos arquivos adicionados ao arquivo e o arquivo será colocado dentro do diretório data .

Isso funciona porque -execdir basicamente faz um cd no diretório pai da coisa encontrada antes de executar o comando.

Para evitar o diretório s3 , use

find . -type d -name data \! -path "./s3/*" -execdir zip -jr data/Archive.zip data ';'
    
por 25.08.2017 / 10:36
3

POSIXly (exceto pelo comando zip , obviamente):

find . -path ./s3 -prune -o -type d -name data -exec sh -c '
   for dir do
     (cd "$dir" && zip -r Archive.zip .)
   done' sh {} +

Ou com zsh -o extendedglob :

for dir (./**/data~*/s3/*(/N)) (cd $dir && zip -r Archive.zip .)

Ou se você não quiser pesquisar recursivamente para data pastas:

for dir (./^s3/data(/N)) (cd $dir && zip -r Archive.zip .)

Ou para ser ainda mais específico (não há necessidade de extendedglob aqui):

for dir (s[124]/data(/N)) (cd $dir && zip -r Archive.zip .)
    
por 25.08.2017 / 10:55