11

Initial situation:

.
├── d0
├── f0
├── f1
│   └── d1
└── f2
    └── f3
        ├── d2
        ├── d3
        └── d4

What I need to do:

I would like to create a zip containing d0, d1 and d4 which must have the fallowing structure:

.
├── d0
├── d1
└── d4

What I have already tried:

I tried it with zip myfiles d0 f1/d1 f2/f3/d4. But this keeps the original folder structure, which is not what I want.

.
├── d0
├── f1
│   └── d1
└── f2
    └── f3
        └── d4

Question How to create a zip with multiple files without the sub-folders?

17

Manually, you can create the zip file and the update it:

zip myfiles d0
(cd f1; zip -u ../myfiles.zip d1)
(cd f2/f3; zip -u ../../myfiles.zip d4)

The parentheses create subshells, and the effect of the cd only lasts in the subshell, so you don't have to cd back to the original directory.

If d1, d2, etc. are actually files and not directories themselves, then use the -j option:

-j
--junk-paths
Store just the name of a saved file (junk the path), and do not store directory names. By default, zip will store the full path (relative to the current directory).

19

You can use find to get the file list and execute zip -j myfiles to pack them ignoring the paths:

find . -name "d[014]" -exec zip -j myfiles {} +

Example

$ tree
.
├── d0
├── f0
├── f1
│   └── d1
└── f2
    └── f3
        ├── d2
        ├── d3
        └── d4

$ find . -name "d[014]" -exec zip -j myfiles {} +
  adding: d1 (stored 0%)
  adding: d4 (stored 0%)
  adding: d0 (stored 0%)

$ unzip -l myfiles.zip
Archive:  myfiles.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2017-10-09 10:47   d1
        0  2017-10-09 10:48   d4
        0  2017-10-09 10:47   d0
---------                     -------
        0                     3 files

However this works for files only, directories will be ignored by zip -j. To get this working for directories too, say we want to pack d0, d1 and the whole f3 directory in the above example, the find line gets a little more complicated:

$ find . \( -name "d[01]" -o -name "f3" \) -exec sh -c 'p=$(pwd); for i in $0 $@; do cd ${i%/*}; zip -ur "$p"/myfiles ${i##*/}; cd "$p"; done' {} +
        zip warning: /home/dessert/myfiles.zip not found or empty
  adding: d1 (stored 0%)
  adding: f3/ (stored 0%)
  adding: f3/d3 (stored 0%)
  adding: f3/d2 (stored 0%)
  adding: f3/d4 (stored 0%)
  adding: d0 (stored 0%)
$ unzip -l myfiles.zip 
Archive:  myfiles.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2017-10-11 10:18   d1
        0  2017-10-11 10:19   f3/
        0  2017-10-11 10:19   f3/d3
        0  2017-10-11 10:19   f3/d2
        0  2017-10-11 10:19   f3/d4
        0  2017-10-11 10:17   d0
---------                     -------
        0                     6 files
18

Using the -j option will remove the path from the file.

zip -j myfiles d0 f1/d1 f2/f3/d4 

reference

  • if any of the paths you are passing are not files but are directories, those directories will not be added to the zip file with the -j option. – Dan Oct 10 '17 at 6:48
  • @dan --if you want all the files in a directory with out the path then zip -j myfiles directory/* – ravery Oct 19 '17 at 8:56

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.