Avoid unwanted path in Zip file

69,467

Solution 1

Your script should use cd or pushd and popd to move into the directory that will be the root of the archive before issuing the zip command. How you do this exactly will depend on how the script knows what to zip up. But, if you want /Users/me/development/something/folder zipped with internal paths of just ./folder, you'd need to do this:

pushd /Users/me/development/something
zip -r /path/to/out.zip ./folder/
popd

That will result in your out.zip containing the relative paths you want.

If you need assistance with scripting that, you'll need to show us your script.

Solution 2

The problem is that the resultant out.zip archive has the entire file path in it.
...
Is it possible to avoid these deep paths when putting a directory into an archive?

Yes. Use the -j option with zip. -j is "junk the path". According to the man page on zip:

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 -j means the following command:

zip -j myarchive.zip file1.txt dir1/file2.txt dir2/dir3/file3.txt ../file4.txt

Will create an archive that looks like:

myarchive.zip
    |
    +-- file1.txt
    +-- file2.txt
    +-- file3.txt
    +-- file4.txt

Solution 3

There is pushd and popd and $OLDPWD. Assuming the $PWD is /Users/me/development do:

pushd something/folder
zip -r $OLDPWD/something/out.zip *
popd

Now the $PWD is back to /Users/me/development

Solution 4

Zip without including paths, but include parent directory, and without having to hardcode its name

A slightly improved version of @quack's accepted answer.

If you are doing this in a script and don't want to have to hardcode the parent directory, you can do this:

pushd /Users/me/development/something/folder/;
zip -r ../out.zip ../$(basename $PWD)
popd;

The ../$(basename $PWD) will ensure that the files are retained in the parent directory when extracted.

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

folder
├── file1
├── file2
├── dir1
│   ├── file3
│   ├── file4

Instead of littering the current directory with the unzipped files:

file1
file2
dir1
├── file3
├── file4
Share:
69,467

Related videos on Youtube

Always Asking
Author by

Always Asking

I'm a jack of many trades, and master of several. I've done quite a bit of software development, web development, database work, and some systems administration.

Updated on September 17, 2022

Comments

  • Always Asking
    Always Asking over 1 year

    I'm making a shell script to package some files. I'm zipping a directory like this:

    zip -r /Users/me/development/something/out.zip /Users/me/development/something/folder/
    

    The problem is that the resultant out.zip archive has the entire file path in it. That is, when unzipped, it will have the whole "/Users/me/development/anotherthing/" path in it. Is it possible to avoid these deep paths when putting a directory into an archive?

    When I run zip from inside the target directory, I don't have this problem.

    zip -r out.zip ./folder/
    

    In this case, I don't get all the junk. However, the script in question will be called from wherever.

    FWIW, I'm using bash on Mac OS X 10.6.

    • Admin
      Admin about 2 years
      Symlink could does the trick. ln -s /path/to/sth .; zip -rq sth.zip sth; rm sth
  • Always Asking
    Always Asking about 14 years
    Perfect. Thanks for the shell command schooling. I like the idea of pushing and popping paths onto the shell "stack".
  • quack quixote
    quack quixote about 14 years
    no problem. i do this in one-liners on the commandline all the time, eg: $ pushd /some/path ; do-something ; popd ... or even with subshells: $ ( cd /some/path ; do-something )
  • joaquin
    joaquin about 14 years
    @~quack: +1 especially for the sub-shell technique in the comment.
  • Chris Johnsen
    Chris Johnsen about 14 years
    Though using && instead of ; is a good idea so that the other command does not run if the cd failed (typo, or other problem): (cd /some/path && do-something)
  • quack quixote
    quack quixote about 14 years
    @Chris Johnsen: that's a good tip. i don't use && and || as often in my one-liners as i do in scripting, but that's part personal style and part personal failing. in this case it is the more suitable grammar.
  • orange80
    orange80 almost 11 years
    Is there not a way to do this without specifying the absolute path for the zip file?
  • ajh158
    ajh158 over 10 years
    @orange80 - I was reading over this Q&A and wondered the same thing. I did a little research and found what seems to be a solution, but I am definitely a bash novice, so take it with a grain of salt. If you want the zip file to be in the directory you are navigating from, you can use dirs and awk to get that directory. I assign that to a variable and use it in my script: LASTDIR=`dirs | awk '{print $2}'`, then instead of zip -r /path/to/out.zip ./folder/, I do zip -r $LASTDIR/bundle.zip
  • jww
    jww over 9 years
    Why are you playing games with the path? Why not use zip -j?
  • Peter Jaric
    Peter Jaric over 8 years
    Doesn't this also junk all paths, even those in the 'folder' directory? I think the OP only wants to get rid of the path on the command line.
  • Moseleyi
    Moseleyi about 8 years
    Life-saving answer. I was looking for option to only zip relative paths while running the script from root. Thanks a lot!
  • Andy
    Andy over 7 years
    @jww i can verify that using the junk-paths argument didn't work for my senario. i needed to cd to the directory.
  • Aaron McMillin
    Aaron McMillin about 7 years
    This might not be the answer for this question, but it's what I need.
  • phil294
    phil294 almost 7 years
    assuming, /path/to was your previous working directory, you could use zip -r ~1/out.zip ... (directory stack shortcuts)
  • Jun
    Jun over 5 years
    zip -j works for me and thus, it zips the files inside that folder without including the folder name.
  • Andrew Schwartz
    Andrew Schwartz over 5 years
    This answer incorrectly assumes user wants a flat zip. This is a bad assumption and can cause the script to fail if two files in different sub-folders have the same name.
  • Lee Meador
    Lee Meador about 4 years
    -j doesn't work right with -r if you want the paths of the files nested inside the specified folder