2

I have file structure similiar to this:

- root_folder_with_bad_name
  - file1
  - file2
  - file3

I need to get zip archive with this structure:

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

I don't know name of files' root_folder, so I can't just do this:

zip archive.zip some_root_folder_name

I want to be able to zip files being inside of that folder. How can I do that?

Zhurik
  • 23
  • How is it that you don't know the name of the folder containing the files? Can't you cd to the parent directory and see? – Nasir Riley Oct 16 '20 at 10:35
  • I need to do this automaticaly. Of course I can do this with pwd and cd, but there should be easier way – Zhurik Oct 16 '20 at 10:38
  • 1
    I don't understand what is the root_folder_with_bad_name, why is it bad? If we cannot say its name, then we cannot (conventionally) access its content. – thanasisp Oct 16 '20 at 10:53
  • 1
    @thanasisp Maybe I'm expressing my idea in the wrong way. Name of root directory doesn't matter. I just need to create archive from inside of the directory itself, like zip archive.zip file1 file2 file3 [some_more_parameters] so i have an archive with directory inside, not just files – Zhurik Oct 16 '20 at 12:07
  • The problem is I need zip archive, not a tarball – Zhurik Oct 16 '20 at 12:41
  • 1
    use gzip then. ;) – Sysadmin Oct 16 '20 at 12:58
  • I think you will take this here so zip -j file.gz path_to_dir/ and you forget that dir, you don't see that again when extracting – thanasisp Oct 16 '20 at 13:06
  • You can't do what you are trying to do automatically or at all unless you know the name of the directory containing the files. You can run find -type f -name *file* on the parent directory and see the name of the folder containing the files but that would actually take longer than just changing to the directory to see and you'd have to make sure that there aren't two files with the same exact name in different directories while also exactly where they are in the hierarchy. – Nasir Riley Oct 16 '20 at 17:59
  • 1
    @roaima Perhaps! I cannot be sure, my understanding was that we want to zip all files in a dir, and when we extract it, to see directly the files, without their parent dir. Hm.. now I see a comment, and combining with the rest, I think the quest is to have a different dir as the parent inside the zipped archive (perhaps). It seems you are right. – thanasisp Oct 16 '20 at 19:21

4 Answers4

3

You can create a temporary directory hierarchy with the target archive folder name, zip that, and then remove it.

This works for bash, presupposing there is no directory (or file) already named archive in the current directory

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

Notice that the new directory hierarchy is linked rather then copied, so (a) it's fast, (b) it doesn't take up any significant extra disk space.

Worked example

# 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

Chris Davies
  • 116,213
  • 16
  • 160
  • 287
2

You appear to want to store files in zip archives with different names or paths than the originals. Aside from removing the path entirely, modifying paths or filenames in zip files does not appear to be possible with commonly available utilities.

As a workaround, you can create the desired directory structure in a temporary folder using hard links.

(I have no idea why people are refering to tar and gzip. They are not relevant since you specifically state you want zip files.)

xiota
  • 526
2

You could use libarchive's bsdtar and its -s option to edit the paths of the files added to the archive:

$ 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

Also this seems to work using a symbolic link, without copying files.

> 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

thanasisp
  • 8,122