I am trying to zip up my application and would like to exclude all of my image directories apart from one.

Consider the following folder structure:

└───/foo // exclude
└───/bar // exclude
└───/foobar // exclude
└───/icons // include

From what I understand, the zip command does not allow the use of regular expressions within it's arguments and as such, I am not sure what to do.

I have done some research and believe there is a way to use ls/find but I am not entirely sure how. Can anyone suggest how I can go about this?

This is my current command (excludes all image directories):

zip -rq application.zip . -x vendor/\* node_modules/\* .git/\* .env public/assets/images/\*

and I believe I need something like this (I haven't got the regex to actually work):

find ./public/assets/images -maxdepth 1 -regex '\.\/(?!icons).* | zip -rq application.zip . -x vendor/\* node_modules/\* .git/\* .env INSERT_FIND_RESULTS_HERE


The full application directory looks similar to the following:

│   .env
│   .env.example
│   .env.pipelines
│   .gitignore
│   artisan
│   etc...
│   │   .htaccess
│   │   index.php
│   │   etc...
│   │
│   └───/assets
│   │   └───/fonts
│   │   └───/images
│   │   │   └───/blog
│   │   │   └───/brand
│   │   │   └───/capabilities
│   │   │   └───/common
│   │   │   └───/contact
│   │   │   └───/icons
│   │   │   └───/misc
│   │   │   └───etc...
│   │
│   └───/js
│   └───/css

I want to zip all of the files excluding:

public/assets/images/ (excluding public/assets/images/icons)

Update 2

Since posting, I have learned that find does not allow lookaheads in it's regular expressions and therefore I need to use a combination of grep and find. As such, this is my latest command (still not working though):

find ./public/assets/images -maxdepth 1 -regex '\./public/assets/images/.*' | grep -oP '\./public/assets/images/(?!icons).*' | xargs zip -rq application.zip . -x vendor/\* node_modules/\* .git/\* .env

Note, I don't know how to use xargs and I believe this is why the above does not work as intended.


2 Answers 2


My suggestion would be to create the archive in two steps:

  1. Create the archive, excluding everything you want to exclude:

    zip -r application.zip . -x 'vendor/*' 'node_modules/*' '.git/*' .env 'public/assets/images/*'
  2. Add to that same archive the one folder that you want to include from the excluded directory:

    zip -r application.zip public/assets/images/icons/

(the default behavior of zip is to add files to an existing archive, if it already exists)

  • 1
    I had no idea that you could add items to an existing archive. This is actually a great solution as it prevents the need for some very long unreadable command
    – Ben Carey
    Commented Jan 20, 2020 at 13:54
  • Also agree with @BenCarey commentary. Also didn't know that it was possible to add items to an existing archive. Commented Jan 20, 2020 at 13:58
  • In my opinion this should be the accepted answer. Commented Jan 20, 2020 at 14:07
  • @BenCarey If you wish to modify the accepted answer, I am ok with that. Commented Jan 20, 2020 at 14:11
  • @PauloTomé - that's very kind of you, I didn't want to without you saying as I know you put a lot of time into your efforts and I very much appreciated that!
    – Ben Carey
    Commented Jan 20, 2020 at 14:12

Please try issuing the following command

find /www \( -path "*/public/assets/images/*" -a  \( ! -path "*/public/assets/images/icons" -a ! -path "*/public/assets/images/icons/*" \) \) -o \( -path "*/.git*" \) -o \( -path "*/vendor*" \) -o \( -path "*/node_modules*" \) -prune -o \( ! -name ".env" \) -exec zip www.zip {} +


The first expression that starts after /www and ends with with the -prune parameter states that the directories .git, vendor, node_modules and public/assets/images except for public/assets/images/icons are to be ignored by find.

! -name ".env" tells find to ignore files named .env

-exec zip www.zip {} + runs the zip command on the selected files, but the command line is built by appending each selected file name at the end; the total number of invocations of the command will be much less than the number of matched files. The result is stored in file www.zip.

  • I don't see how this will work because it will include all of the directories alongside the public/assets/images/icons directory. It doesn't mention anything about icons. Also, what does the @ do?
    – Ben Carey
    Commented Jan 18, 2020 at 13:42
  • Sorry. You are right. Will fix my answer. The @ states the end of exclude supplied arguments. Commented Jan 18, 2020 at 13:45
  • This is the latest I have (not working but close I think): find ./public/assets/images -maxdepth 1 -regex '\./public/assets/images/.*' | grep -oP '\./public/assets/images/(?!icons).*' | zip -rq application.zip . -x vendor/\* node_modules/\* .git/\* .env -@
    – Ben Carey
    Commented Jan 18, 2020 at 13:46
  • If we can find a way to insert the result from grep into the arguments of zip then I think we have it. Do you know how to do that?
    – Ben Carey
    Commented Jan 18, 2020 at 13:51
  • In my opinion it is not necessary to use grep to solve this problem. Commented Jan 18, 2020 at 14:00

You must log in to answer this question.

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