Como posso recursivamente zipar arquivos em sua própria pasta?

1

Eu tenho a seguinte estrutura de diretórios:

/Data
 - file 1
 - file 2

  /Folder1

   - file 3
   - file 4

  /Folder2
   - file 5
   - file 6

    /Folder3
      - file 7
      - file 8

No Linux, quero compactar arquivos (excluindo pastas) em cada diretório e criar um arquivo 7z (ou zip) em cada pasta, resultando no seguinte:

/Data
     Data.7z (Note: this should contain only file1 & 2, not any sub directories)

      /Folder1

       Folder1.7z (this should contain only file3 & 4, not any sub directories)

      /Folder2
       Folder2.7z (this should contain only file5 & 6, no Folder3)

        /Folder3
          Folder3.7z (should contain only file7 & 8)

O script a seguir funciona no primeiro diretório, mas não nos subdiretórios:

for i in */ ; do base=$(basename “$i”) ; cd $base ; 7za a -t7z -r $base * ; .. ; cd .. ; done;

Como posso conseguir isso?

    
por alien250 13.02.2018 / 00:15

2 respostas

2

Se você quiser usar 7z , a parte complicada parece estar persuadindo a não a recorrer; o parâmetro -r- indicado pela documentação parece não ser funcional, e a solução sugerida do software author é para excluir subdiretórios com a expressão curinga -x!*/

Então, dado

$ tree Data
Data
├── file1
├── file2
├── Folder1
│   ├── file3
│   └── file4
├── Folder2
│   ├── file5
│   └── file6
└── Folder3
    ├── file7
    └── file8

3 directories, 8 files

então

find Data -type d -execdir sh -c 'cd "" && 7z a "".7z -x!*/ && cd -' sh {} \;

resulta em

$ tree Data
Data
├── Data.7z
├── file1
├── file2
├── Folder1
│   ├── file3
│   ├── file4
│   └── Folder1.7z
├── Folder2
│   ├── file5
│   ├── file6
│   └── Folder2.7z
└── Folder3
    ├── file7
    ├── file8
    └── Folder3.7z

3 directories, 12 files

onde, por exemplo, podemos verificar que Folder2.7z contém apenas os arquivos da sua própria pasta usando

$ 7z l Data/Folder2/Folder2.7z 

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_CA.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM)2 Duo CPU     P9600  @ 2.53GHz (1067A),ASM)

Scanning the drive for archives:
1 file, 128 bytes (1 KiB)

Listing archive: Data/Folder2/Folder2.7z

--
Path = Data/Folder2/Folder2.7z
Type = 7z
Physical Size = 128
Headers Size = 128
Solid = -
Blocks = 0

   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2018-02-12 18:37:37 ....A            0            0  file5
2018-02-12 18:37:37 ....A            0            0  file6
------------------- ----- ------------ ------------  ------------------------
2018-02-12 18:37:37                  0            0  2 files

Observação: !*/ pode exigir escape adicional em ambientes (como o shell bash interativo), em que ! é um operador de expansão de histórico.

    
por steeldriver 13.02.2018 / 02:59
0

Este é um código não testado, usado apenas com 'echo', já que não gosto de finalizar com vários arquivos zip. E é a sintaxe do zip do phantasy, já que eu não sei 7za, mas vou explicar:

find . -type d -execdir /.../ad-hoc.sh {} ";"

O script ad-hoc.sh deve ser endereçado com um caminho absoluto e não deve estar no caminho atual, para não afetar o resultado, mas pode estar no parentdir:

find . -type d -execdir $PWD/../ad-hoc.sh {} ";"

e, se não for executável, ser explicitamente chamado:

find . -type d -execdir bash $PWD/../ad-hoc.sh {} ";"

O Find deve procurar no diretório atual, somente pelos arquivos do tipo d (dirs), onde -executar um bashscript com o parâmetro {}, o diretório encontrado.

Ok - o que é o ad-hoc.sh, nós executamos na dir e nos subdiretórios? É outro achado:

#!/bin/bash
dir=
find $dir -maxdepth 1 -type f -exec echo zip -o "$dir.zip" {} +

-maxdepth 1 impede que o find procure por subdiretórios, -tipo diz que apenas opera em arquivos. -exec lança um comando, para testar "echo zip ...", mas se parece promissor (você faz backups com frequência, não é?), você - bem, aqui começa meu pseudo código: -o: = -output "$ PWD.zip" e {} + é a lista de arquivos.

tree
.
├── buch-klein.kry
├── buch.kry
├── crypt
│   ├── moveto.sh.crypt
│   └── sub1
│       ├── foo.crypt
│       └── sub2
│           └── bar.crypt
├── original
│   ├── 1
│   │   └── 2
│   │       └── 3
│   ├── moveto.sh
│   └── sub1
│       └── sub2
│           └── up3 -> ../../../nr
├── outputfile.txt
├── rot.sh
└── zoom.sh

find . -type d -execdir $PWD/../ad-hoc.sh {} ";" 
zip -o ./..zip ././buch-klein.kry ././rot.sh ././buch.kry ././zoom.sh ././outputfile.txt
zip -o ./original.zip ./original/moveto.sh
zip -o ./crypt.zip ./crypt/moveto.sh.crypt
zip -o ./sub1.zip ./sub1/foo.crypt
zip -o ./sub2.zip ./sub2/bar.crypt

Todo arquivo com extensão é um arquivo regular, e todo arquivo sem é um diretório ou um symlink para um diretório (up3).

O {} tem que ser o último elemento de um comando find -exec antes do término ";" ou +, então você tem que construir seu comando 7z de acordo.

então se o seu comando 7za for

      7za a -t7z -r $dir.7za *

o ad-hoc.sh pode ser assim:

#!/bin/bash
dir=
find $dir -maxdepth 1 -type f -exec echo 7za -t7z -r "$dir.7za" {} +
    
por user unknown 13.02.2018 / 02:11