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