Zip all files in directory?

Is there a way to zip all files in a given directory with the zip command? I’ve heard of using *.*, but I want it to work for extensionless files, too.

Asked By: tkbx

||

You can just use *; there is no need for *.*. File extensions are not special on Unix. * matches zero or more characters—including a dot. So it matches foo.png, because that’s zero or more characters (seven, to be exact).

Note that * by default doesn’t match files beginning with a dot (neither does *.*). This is often what you want. If not, in bash, if you shopt -s dotglob it will (but will still exclude . and ..). Other shells have different ways (or none at all) of including dotfiles.

Alternatively, zip also has a -r (recursive) option to do entire directory trees at once (and not have to worry about the dotfile problem):

zip -r myfiles.zip mydir

where mydir is the directory containing your files. Note that the produced zip will contain the directory structure as well as the files. As peterph points out in his comment, this is usually seen as a good thing: extracting the zip will neatly store all the extracted files in one subdirectory.

You can also tell zip to not store the paths with the -j/--junk-paths option.

The zip command comes with documentation telling you about all of its (many) options; type man zip to see that documentation. This isn’t unique to zip; you can get documentation for most commands this way.

Answered By: derobert

Another way would be to use find and xargs: (this might include a “.” directory in the zip, but it should still extract correctly. With my test, zip stripped the dot before compression)
find . -type f -exec zip zipfile.zip {} +

(The + can be replaced with ; if your version of find does not support the + end for exec. It will be slower though…)

This will by default include all sub-directories. On GNU find -maxdepth can prevent that.

Answered By: Gert van den Berg

In my case I wanted to zip each file into its own archive, so I did the following (in zsh):

$ for file in *; do zip ${file%.*}.zip $file; done
Answered By: Resigned June 2023

Another (slow) method to do this (which adds one file to the zip at a time):

for f in * .[^.]*; do
    [ -r "$f" ] || continue # Skip directories or non-existant files (Probably ".[^.]*" if directory has no dotfiles). Using -e will allow directories to be used as well
    zip zipfile.zip "$f" # If directories are included, you probably want to add -r
done

This has the dotfile issues of * (workaround added) and would be start zip once for each file, adding it to the archive. In bash, it would deal with a large amount of files.

It would be slower than most of the other methods, but is relatively simple.

Answered By: Gert van den Berg

Not .zip files, but gzip * is a brief command that will compress each file in a dir into its own .gz and delete the original. Really handy in many cases, as many other tools can work with the .gz files directly.

user@computer:~/test$ touch test1.txt
user@computer:~/test$ touch test2.txt
user@computer:~/test$ touch test3.txt
user@computer:~/test$ ls
test1.txt  test2.txt  test3.txt
user@computer:~/test$ gzip *
user@computer:~/test$ ls
test1.txt.gz  test2.txt.gz  test3.txt.gz
Answered By: CoderGuy123

If you want to avoid using globs you can do

cd mydir
zip -r ../my.zip .

It’s not pretty, but it gets the job done 🙂

Answered By: Alexander Torstling
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.