Take the 2-minute tour ×

I admit this question was asked here before:

Like Zip into separate files where the person who asked didn't specify the OS he used and received no answers.

I need to separate a huge directory into multiple .zip files that are not interdependent on each other. So, instead of:


I would like the following set of files instead:


Basically this is my question. I'm on OS X so a shell script or AppleScript would be the easiest way to go.

In addition, here is a guy who asked the same thing - only he wanted to create a .tar archive: How to Creating separate archives for a set of files

The answer is correct, but it will result in tar files:

for file in `ls *`; do tar -czvf $file.tar.gz $file ; done

Any help with this is appreciated.

PS: This last part is just for those of you who are fit in Keyboard Maestro:

I also tried to perform this in Keyboard Maestro, I have a "for each" action setup which determines the file paths and then triggers a shell script. The output is correct and the macro works if I paste it in the terminal (e.g. zip /Users/me/Desktop/test /Users/me/Desktop/test.txt).

However, when I pass the two variables to the shell script in Keyboard Maestro won't work:
zip "$KMVAR_zipPath" "$KMVAR_sourcePath"


share|improve this question
Well, have you tried replacing tar -czvf with zip in the tar solution? –  Daniel Beck May 30 '12 at 6:15
@DanielBeck Yes, that was the first thing I tried. –  pattulus May 30 '12 at 7:14

1 Answer 1

up vote 5 down vote accepted

The solution is pretty easy. If you want to do this for every file, recursively, use find. It will list all files and directories, descending into subdirectories too.

find . -type f -execdir zip '{}.zip' '{}' \;


  • The first argument is the directory you want to begin in, .
  • Then we will restrict it to find files only (-type f)
  • The -execdir option allows us to run a command on each file found, executing it from the file's directory
  • This command is evaluated as zip file.txt.zip file.txt, for example, since all occurrences of {} are replaced with the actual file name. This command needs to be ended with \;

Of course, find has more options. If instead you just want to stay in your current directory, not descending into subdirectories:

find . -type f -maxdepth 1 -execdir zip '{}.zip' '{}' \;

If you want to restrict it to certain file types, use the -name option (or -iname for case-insensitive matching):

find . -type f -name "*.txt" …

Anything else (including looping with for over the output of ls *) is pretty ugly syntax in my opinion and likely to break, e.g. on files with spaces in their name or due to too many arguments.

share|improve this answer
Thanks, but it doesn't work here. Output when paste the recursive one: cl.ly/Gzbh --- I wouldn't mind specifying the files to zip by extension if that makes it easier. –  pattulus May 30 '12 at 7:19
Oops, see my update. zip needs an extension if the files have one. For files without an extension it'll automatically append .zip –  slhck May 30 '12 at 7:23
Nice, it works splendid. Thank you very much. --- For the bonus points: would you mind telling me how to do this for a certain file type, c.f. with the extension ".txt"? I tried some variants but… –  pattulus May 30 '12 at 7:28
See my second update. Check the manpage of find, everything's explained pretty nicely, and if you haven't really used it before, it's probably one of the most useful tools on a *nix system. –  slhck May 30 '12 at 7:39
Thanks for the update. I'm looking to the "man find" and it's really seems like a big useful tool. –  pattulus May 30 '12 at 7:40

Your Answer


