How to create a zip with multiple files without sub-folders?
Andrew Mclaughlin
Initial situation:
.
├── d0
├── f0
├── f1
│ └── d1
└── f2 └── f3 ├── d2 ├── d3 └── d4What I need to do:
I would like to create a zip containing d0, d1 and d4 which must have the fallowing structure:
.
├── d0
├── d1
└── d4What 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 └── d4QuestionHow to create a zip with multiple files without the sub-folders?
3 Answers
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 filesHowever 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 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).
Using the -j option will remove the path from the file.
zip -j myfiles d0 f1/d1 f2/f3/d4 2