How to zip multiple files into separate archives?

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:

file1.zip
file2.z01
file3.z02

I would like the following set of files instead:

file1.zip
file2.zip
file3.zip

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

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"


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' '{}' \;

Explanation:

  • 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.