247

I'm trying to zip a directory (on Unix via SSH) but I need to exclude a couple of subdirectories (and all files and directories within them).

So far I have this:

zip -r myarchive.zip dir1 -x dir1/ignoreDir/**/* 

That doesn't seem to work though.

I also tried

zip -r myarchive.zip dir1 -x dir1/ignoreDir1/* dir1/ignoreDir2/*

However that will still include subdirectories within ignoreDir1 and ignoreDir2.

The subdirectory structure in the directories that I want to exclude is quite substantial so I can't simply add each directory to the -x argument.

Does anyone know how to do this?

1
  • @AlexanderMills - See this question.
    – jww
    Jan 1, 2018 at 1:02

9 Answers 9

261

The actual command I need is:

zip -r myarchive.zip dir1 -x dir1/ignoreDir1/**\* dir1/ignoreDir2/**\*
7
  • 4
    This did not work for me on osx. @pathfilder answer did though.
    – rynop
    Dec 12, 2014 at 20:44
  • 37
    Instead of this: -x dir1/ignoreDir1/**\*, you can do this: -x dir1/ignoreDir1/\* Jan 22, 2016 at 14:37
  • 10
    This worked for me zip -r theme.zip ./theme -x ./theme/node_modules/\*
    – AhmadKarim
    Apr 9, 2021 at 18:14
  • 1
    @AhmadKarim exactly what I needed for node_modules :)
    – Yashank
    Apr 14, 2021 at 7:13
  • 5
    On MacOS I was successful with: zip -r theme.zip theme -x theme/node_modules/\* or zip -r theme.zip theme -x "theme/node_modules/*" Sep 15, 2021 at 4:53
166

For my particular system (Mac OS) in order to exclude a directory I had to put quotes around my excluded directories and it worked like a charm. You need to do this because sometimes directories and files can be named with spaces and special characters that would cause this to fail without the quotes. Its easier than escaping the spaces and special characters.

zip -r myarchive.zip dir1 -x "dir1/ignoreDir1/*" "dir1/ignoreDir2/*"

Notes:

-- this excluded both the directory to exclude and all files inside it.

-- You must use the full path to the directories you want to exclude!

8
  • 14
    This is the one that works on Mac OS. :-) Jun 1, 2015 at 12:55
  • 30
    As nobody has explained the reason for requiring either quoting the paths or escaping the asterisk, the reason is this: If the path is not quoted or the wildcard escaped, the shell will perform wildcard expansion before passing them to zip, which will receive a list of paths to entries in the specified directories, but not paths to files within subdirectories of those, thus causing zip to not to ignore everything under the given directories.
    – zagrimsan
    Dec 1, 2015 at 13:57
  • 1
    I think originally one of the reasons this worked was because on Mac OS there were spaces in my directories and this avoided needing a \
    – pathfinder
    Oct 14, 2017 at 20:08
  • 1
    Relative paths works for me Jan 6, 2020 at 16:53
  • 1
    Notice that when using a file with the exception list (zip -r myarchive.zip dir1 [email protected]), it's not necessary to use quotes neither escape with * in the file. Use just like: dir1/ignoreDir1/* dir1/ignoreDir2/*
    – villamejia
    Feb 16, 2023 at 14:59
17

@sulman using:

zip -r myarchive.zip dir1 -x dir1/ignoreDir1/**\* dir1/ignoreDir2/**\*

will still include dir1/ignoreDir1/ empty folder in the zip archive, using:

zip -r myarchive.zip dir1 -x dir1/ignoreDir1** dir1/ignoreDir2**

will do the trick, you can also use a leading ** to search in subfolders instead of only dir1

1
  • Ah ok! Thanks for shedding the light on this!
    – sulman
    Oct 30, 2013 at 14:51
9

The following will do

zip -r myarchive.zip dir1 -x dir1/ignoreDir1\* dir1/ignoreDir2\*

What did you need the ** for, @sulman?

It works like a charm for me as follows:

[root@ip-00-000-000-000 dir1]# ls -lrt dir1/ 
total 16
drwxr-xr-x 2 root root 4096 Oct 31 07:38 ignoredir1
drwxr-xr-x 2 root root 4096 Oct 31 07:38 ignoredir2
drwxr-xr-x 2 root root 4096 Oct 31 07:39 dir3
-rw-r--r-- 1 root root    8 Oct 31 07:39 test.txt

[root@ip-00-000-000-000 temp]# zip -r dir1.zip dir1 -x dir1/ignoredir1\* dir1/ignoredir2\*
  adding: dir1/ (stored 0%)
  adding: dir1/dir3/ (stored 0%)
  adding: dir1/dir3/test3.txt (deflated 13%)
  adding: dir1/test.txt (stored 0%)
2
  • I don't know why the ** is needed. Maybe someone else can shed some light on this?
    – sulman
    Sep 17, 2012 at 8:55
  • Sorry, @sulman, I typed wrongly. What I meant is as per my latest edit. Works a like a charm for me :)
    – ericn
    Oct 31, 2012 at 7:52
3

Just like other answers, but excluding directories entirely, instead of excluding all contents of directories:

zip -r myarchive.zip dir1 -x dir1/ignoreDir1/\* dir1/ignoreDir2/\*
2

In Ubuntu Server this commands works for zip a file excluding some folders, but with a little differences:

If you wanna zip without keep empty folders:

zip -r myarchive.zip dir1 -x dir1/ignoreDir1/**\* dir1/ignoreDir2/**\*

If you wanna zip keep empty folders:

zip -r myarchive.zip dir1 -x dir1/ignoreDir1\* dir1/ignoreDir2\*

By example:

zip -r testtt.zip uploads/2013/ -x uploads/2013/03/**\* uploads/2013/04/**\*
zip -r testtt.zip uploads/2013/ -x uploads/2013/03\* uploads/2013/04\*
2

I haven't looked at the code, but what appears to be happening is that -R creates a list of paths, and -x does a regex on each element of that list to include or exclude it. Thus, the argument to -x is basically a text regex -- or that's how you can think of it.

To exclude all instances of a folder name (and, actually, any files that have the same name), the command would be (I have shortened the prefix that will include ignoreDir1 and ignoreDir2):

zip -r myarchive.zip dir1 -x "*ignore*"

To avoid excluding files, you can add the path separators (but you need to add the ? to the regex pattern to include both numbered folders):

zip -r myarchive.zip dir1 -x "*/ignoreDir?/*"

I think it's more readable to quote the argument instead of escaping the shell special characters.

1

I found this to work from David R Heffelfinger:

zip -r myarchive.zip dir1 -x dir1/ignoreDir1\* dir1\ignorDir2\*

It excluded the directory and its contents.

1
  • Surely the backslash between dir1 and ignorDir2 is meant to be a forward slash. Do you mean for the other backslashes to be backslashes? If you do, then you have just copied fuzzybee's answer from two years ago. Oct 3, 2014 at 19:48
-2

For me worked: zip -9 -r ~/folded.zip online -x folder/folder2/folder3/foldern/\*.

Seems to be that the asterisk must be escaped.

3
  • 3
    How does this differ from the solution by Rick Ehrahrt a year ago, or Eric's (a few more years ago)? Please do read the provided solutions before posting a new one...
    – zagrimsan
    Dec 1, 2015 at 13:50
  • Because I added a backslash before the asterisk (that is to escape the asterisk). In the linux version at my work doesn't work if i don't do that. Dec 15, 2015 at 9:30
  • Also Rick Ehrahrt (2014) and eric (2012) posted the same solution (to escape the asterisk). There's nothing wrong with the solution, but posting the same one multiple times doesn't make sense unless one can significantly add depth to the solution by explaining why the solution works. In a simple case like this, there's nothing to be explained more. Please don't take this personally, my only intention here is to help in keeping SU clean and concise so users can find the best solution with the least effort.
    – zagrimsan
    Dec 15, 2015 at 10:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .