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?

9
  • 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? Oct 16, 2020 at 10:35
  • 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, 2020 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, 2020 at 12:07
  • 1
    use gzip then. ;)
    – Sysadmin
    Oct 16, 2020 at 12:58
  • 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, 2020 at 19:21

4 Answers 4

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
1
  • My solution already doesn't use extra disk space - see the -l flag for cp
    – roaima
    Oct 17, 2020 at 18:58
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.)

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
4
  • @roaima, well yes, bsdtar can handle tar obviously, and many other format for extraction and a few for creation. Oct 18, 2020 at 5:44
  • Sorry - meant for rewriting names in a pipe
    – roaima
    Oct 18, 2020 at 6:27
  • @roaima. Yes, the standard command for handling tar files (pax) also has a -s option. I believe GNU tar has --transform for that. Oct 18, 2020 at 6:36
  • Thank you (deleting shortly). I knew pax had a transform but I also see that despite it being POSIX it's not a utility installed as standard
    – roaima
    Oct 18, 2020 at 7:44
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
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.