275

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?

Gareth
  • 19,080
sulman
  • 5,681

9 Answers9

283

The actual command I need is:

zip -r myarchive.zip dir1 -x dir1/ignoreDir1/**\* dir1/ignoreDir2/**\*
sulman
  • 5,681
173

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!

pathfinder
  • 1,831
18

@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

Gianluca P.
  • 281
  • 2
  • 3
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%)
Andy
  • 113
ericn
  • 231
4

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.

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\*
JorgeM
  • 433
2

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.

0

Use Single Quotes
Bash wildcard expansion will interfere with supplying * in an argument. Either escape each special char with \ or using single quotes '*'.

I was trying to exclude .git and needed to be careful not to exclude .github. So my command:

zip -r my-archive.zip . -x '.git/*'

or with escapes:

zip -r my-archive.zip . -x \.git/\*
Peter L
  • 181
  • 1
  • 3