Exclui arquivos de nível superior do zip, mas inclui diretórios e conteúdo

1

Isso está me deixando louca. Todos os resultados do Google são para o cenário inverso.

Então eu tenho uma estrutura de diretórios como:

MyFiles
|    file1
|    file2
|    file3
|    MoreFiles
|    |    file4
|    |    file5

E o que eu quero é um arquivo (preferencialmente zip enquanto estou passando processo para usuários não-tar, mas pontos de bônus para respostas mostrando como em zip e tar) que se parece com:

archive.zip
|    MoreFiles
|    |    file4
|    |    file5

Para que os arquivos de nível superior sejam excluídos, mas os subdiretórios e seus arquivos são incluídos.

Até agora, o melhor que consegui encontrar foi:

zip -r archive.zip MyFiles -x "."

mas isso exclui todos os arquivos em todos os níveis, então acabo ficando com a estrutura de diretórios. Eu só quero excluir os diretórios sentados diretamente no diretório de destino.

Oh! E, na verdade, meu caso de uso do mundo real é excluir o conteúdo de um subdiretório específico, portanto, trabalhar a partir do próximo nível mais profundo não é uma solução alternativa. O cenário real é:

MyFiles
|    file1
|    file2
|    file3
|    Level1Files1
|    |    file4
|    |    file5
|    |    Level2Files1
|    |    |    file6
|    |    |    file7
|    |    Level2Files2
|    |    |    file8
|    |    |    file9
|    Level1Files2
|    Level1Files3

com o objetivo final de incluir tudo no nível superior, mas excluir arquivos dentro do subdiretório específico, mas não excluir os subdiretórios dentro desse primeiro subdiretório ou seu conteúdo, para que, se eu quisesse excluir os arquivos principais do subdiretório Level1Files1 acima, o resultado seria:

archive.zip
|    file1
|    file2
|    file3
|    Level1Files1
|    |    Level2Files1
|    |    |    file6
|    |    |    file7
|    |    Level2Files2
|    |    |    file8
|    |    |    file9
|    Level1Files2
|    Level1Files3
    
por Anthony 08.04.2015 / 05:56

1 resposta

1

Com o uso criativo de curingas.

$ tree MyFiles
MyFiles
├── dira
│   ├── file1
│   ├── file2
│   └── file3
├── dirb
│   ├── file1
│   ├── file2
│   └── file3
├── dirc
│   ├── file1
│   ├── file2
│   └── file3
├── file1
├── file2
└── file3

O que precisamos fazer é não dizer o zip sobre os arquivos raiz. Os curingas de Bash nos permitem especificar isso com zip -r archive.zip MyFiles/*/ . Observe que o curinga é formatado para poder corresponder apenas a um diretório. Usando isso, conseguimos:

$ zip -r archive.zip MyFiles/*/
  adding: MyFiles/dira/ (stored 0%)
  adding: MyFiles/dira/file1 (stored 0%)
  adding: MyFiles/dira/file2 (stored 0%)
  adding: MyFiles/dira/file3 (stored 0%)
  adding: MyFiles/dirb/ (stored 0%)
  adding: MyFiles/dirb/file1 (stored 0%)
  adding: MyFiles/dirb/file2 (stored 0%)
  adding: MyFiles/dirb/file3 (stored 0%)
  adding: MyFiles/dirc/ (stored 0%)
  adding: MyFiles/dirc/file1 (stored 0%)
  adding: MyFiles/dirc/file2 (stored 0%)
  adding: MyFiles/dirc/file3 (stored 0%)

$ less archive.zip
Archive:  archive.zip
Zip file size: 1960 bytes, number of entries: 12
drwxrwxr-x  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dira/
-rw-rw-r--  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dira/file1
-rw-rw-r--  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dira/file2
-rw-rw-r--  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dira/file3
drwxrwxr-x  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dirb/
-rw-rw-r--  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dirb/file1
-rw-rw-r--  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dirb/file2
-rw-rw-r--  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dirb/file3
drwxrwxr-x  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dirc/
-rw-rw-r--  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dirc/file1
-rw-rw-r--  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dirc/file2
-rw-rw-r--  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dirc/file3
12 files, 0 bytes uncompressed, 0 bytes compressed:  0.0%

Subdiretórios e seus conteúdos apenas.

Para a questão bônus:

tar -xcvf archive.tar.gz MyFiles/*/

Exclusões mais específicas exigiriam o uso muito criativo de curingas, regex, find e pipes. Algumas idéias vêm à mente, mas nada bonito ou confiável. Nesse ponto, você está entrando no script, e pode muito bem apenas percorrer loops.

Editar: há uma maneira não totalmente insana de fazer isso com subdiretórios. eu acho.

zip -r archive.zip MyFiles/*/ -x \
         $(find ./MyFiles/subdir/toexclude/topfiles -maxdepth 1 -not -type d)

Tome nota da nova linha de escape - tudo isso deve ser uma linha. Modifique conforme necessário. Eu testei e excluiu os arquivos no MyFiles/subdir/toexclude/topfiles , mas incluiu seus 3 subdiretórios e assim por diante.

Isso deve ser feito pelo seu exemplo:

$ cd MyFiles
$ zip -r archive.zip * -x $(find -maxdepth 1 ./Level1Files1 -not -type d)
    
por 08.04.2015 / 06:37