321

I need to create a zip file using this command:

zip /dir/to/file/newZip /data/to/zip/data.txt

This works, but the created zip file creates a directory structure mimicking the directory to the raw file. It is a lot of extra folders that I don't need.

I didn't find an answer in a cursory glance over the man page or a Google hunt.

petezurich
  • 9,280
  • 9
  • 43
  • 57
Jake
  • 4,134
  • 2
  • 16
  • 20
  • [Unix zip directory but excluded specific subdirectories](https://superuser.com/q/312301/173513), [how to exclude directories and file zipping a directory?](https://askubuntu.com/q/371579), [How to exclude a directory when zipping files](https://unix.stackexchange.com/q/219101/56041), etc. – jww Jan 01 '18 at 01:05
  • 2
    I was thinking this question predated all of those other stack exchanges but alas superuser's post actually is older than this one. If there is something I can do here to help let me know. This must be quite the hot answer since google still drives so much traffic here. :D – Jake Jan 02 '18 at 03:27

7 Answers7

467

You can use -j.

-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).
Lars Kotthoff
  • 107,425
  • 16
  • 204
  • 204
  • 41
    If `-j` doesn't work for your directory (together with `-r`) checkout [this answer](http://superuser.com/a/119661/45285) – czerasz Mar 26 '16 at 02:00
  • sometime it just doesn't work... prefer @czerasz link ;) which basically is a pushd popd combo – TecHunter Oct 28 '16 at 08:33
63

Using -j won't work along with the -r option.
So the work-around for it can be this:

cd path/to/parent/dir/;
zip -r complete/path/to/name.zip ./* ;
cd -;

Or in-line version

cd path/to/parent/dir/ && zip -r complete/path/to/name.zip ./* && cd -

you can direct the output to /dev/null if you don't want the cd - output to appear on screen

Vikas Tawniya
  • 1,323
  • 1
  • 13
  • 22
  • Actually, you might want do the following: `cd path/to/parent/dir/ && zip -r ../../../../name.zip ./* && cd -` – eddyP23 Jan 29 '19 at 09:43
  • @eddyP23 How does it make any difference ? Rather it will cause you to add no. of parentDir(..) for each directory in the path :| – Vikas Tawniya Jan 31 '19 at 09:51
  • The result is the same, I agree. But in automated scripts that run in many different environments, you usually avoid global paths, because you have no idea what the global path will be. But from the `cd path/to/parent/dir/` you can calculate number of double dots `../` easily. – eddyP23 Jan 31 '19 at 11:53
  • @eddyP23 makes sense – Vikas Tawniya Feb 01 '19 at 11:54
36

Use the -j option:

   -j     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 path).
Dan D.
  • 73,243
  • 15
  • 104
  • 123
20

Somewhat related - I was looking for a solution to do the same for directories. Unfortunately the -j option does not work for this :(

Here is a good solution on how to get it done: https://superuser.com/questions/119649/avoid-unwanted-path-in-zip-file

petezurich
  • 9,280
  • 9
  • 43
  • 57
flaky
  • 6,816
  • 4
  • 29
  • 46
7

Alternatively, you could create a temporary symbolic link to your file:

ln -s /data/to/zip/data.txt data.txt
zip /dir/to/file/newZip !$
rm !$

This works also for a directory.

MirkoBanchi
  • 2,173
  • 5
  • 35
  • 52
7

Retain the parent directory so unzip doesn't spew files everywhere

When zipping directories, keeping the parent directory in the archive will help to avoid littering your current directory when you later unzip the archive file

So to avoid retaining all paths, and since you can't use -j and -r together ( you'll get an error ), you can do this instead:

cd path/to/parent/dir/;
zip -r ../my.zip "../$(basename "$PWD")"
cd -;

The "../$(basename "$PWD")" is the magic that retains the parent directory.

So now unzip my.zip will give a folder containing all your files:

parent-directory
├── file1
├── file2
├── dir1
│   ├── file3
│   ├── file4

Instead of littering the current directory with the unzipped files:

file1
file2
dir1
├── file3
├── file4
Jimmix
  • 5,644
  • 6
  • 44
  • 71
AndrewD
  • 4,924
  • 3
  • 30
  • 32
  • 2
    However in the ZIP archive an additional unwanted parent directory `/../` is created, like `/../parent/sub/` – escalator Sep 29 '21 at 11:59
3

Just use the -jrm option to remove the file and directory structures

zip -jrm /path/to/file.zip /path/to/file
petezurich
  • 9,280
  • 9
  • 43
  • 57
Ood
  • 55
  • 1
  • 1
  • 4
    be carefull, -m --move Move the specified files into the zip archive; actually, this deletes the target directories/files after making the specified zip archive. If a directory becomes empty after removal of the files, the directory is also removed. No deletions are done until zip has created the archive without error. This is useful for conserving disk space, but is potentially dangerous so it is recommended to use it in combination with -T to test the archive before removing all input files. – catalint Jun 04 '20 at 14:52
  • The "-m" flag being on this could HUGELY impact people, possibly even give a couple scares, or even worse, loss of data (without, for example, the -T flag as the commenter above mentioned). -1 – SuperJumpBros Mar 11 '23 at 02:17