Como compactar arquivos como uma pasta

Oct 16 2020

Tenho uma estrutura de arquivo semelhante a esta:

- root_folder_with_bad_name
  - file1
  - file2
  - file3

Preciso obter um arquivo zip com esta estrutura:

- archive.zip
  - some_folder
    - file1
    - file2
    - file3

Não sei o nome dos arquivos root_folder, então não posso simplesmente fazer isso:

zip archive.zip some_root_folder_name

Eu quero ser capaz de compactar os arquivos dentro dessa pasta. Como eu posso fazer isso?

Respostas

2 xiota Oct 16 2020 at 22:49

Você parece querer armazenar arquivos em ziparquivos com nomes ou caminhos diferentes dos originais. Além de remover o caminho inteiramente, a modificação de caminhos ou nomes de ziparquivos em arquivos não parece ser possível com os utilitários comumente disponíveis.

Como alternativa, você pode criar a estrutura de diretório desejada em uma pasta temporária usando links físicos.

(Não tenho ideia do motivo pelo qual as pessoas estão se referindo a tare gzip. Eles não são relevantes, pois você afirma especificamente que deseja ziparquivos.)

3 roaima Oct 17 2020 at 02:22

Você pode criar uma hierarquia de diretório temporário com o nome da pasta de arquivo de destino, compactá-la e removê-la.

Isso funciona bash, pressupondo que não haja um diretório (ou arquivo) já nomeado archiveno diretório atual

(
    shopt -s extglob
    mkdir archive &&
        cp -al !(archive) archive &&
        zip -r archive.zip archive
    rm -rf archive
)

Observe que a nova hierarquia de diretório é vinculada em vez de copiada, então (a) é rápida, (b) não ocupa nenhum espaço extra significativo em disco.

Exemplo trabalhado

# Set up the files in a directory
mkdir secret_name; touch secret_name/file{1,2,3}
cd secret_name/

# Now create the archive
( shopt -s extglob; mkdir archive && cp -al !(archive) archive/ && zip -r archive.zip archive; rm -rf archive )

# List the archive
unzip -l archive.zip

Archive:  archive.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2020-10-16 19:21   archive/
        0  2020-10-16 19:12   archive/file2
        0  2020-10-16 19:12   archive/file3
        0  2020-10-16 19:12   archive/file1
---------                     -------
        0                     4 files
2 StéphaneChazelas Oct 17 2020 at 03:17

Você pode usar o libarchive bsdtare sua -sopção para editar os caminhos dos arquivos adicionados ao arquivo:

$ ls file1 file2 file3 $ bsdtar --format=zip -'s|^\.|some_folder|' -cf ../file.zip .
$ unzip -l ../file.zip
Archive:  ../file.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2020-10-16 21:15   some_folder/
        0  2020-10-16 21:15   some_folder/file1
        0  2020-10-16 21:15   some_folder/file3
        0  2020-10-16 21:15   some_folder/file2
---------                     -------
        0                     4 files
1 thanasisp Oct 17 2020 at 02:54

Também parece funcionar usando um link simbólico, sem copiar arquivos.

> ls old_parent/
file1  file2

> ln -s old_parent new_parent

> zip -r archive.zip new_parent
  adding: new_parent/ (stored 0%)
  adding: new_parent/file2 (deflated 22%)
  adding: new_parent/file1 (deflated 38%)

> unzip -l archive.zip 
Archive:  archive.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2020-10-16 22:48   new_parent/
       50  2020-10-14 08:18   new_parent/file2
      348  2020-10-16 13:58   new_parent/file1
---------                     -------
      398                     3 files

> rm new_parent