I’m the author of a utilty that makes compressing projects using zip
a bit easier, especially when you have to compress regularly, such as for updating projects submitted to an application store (like Chrome’s Web Store).
I’m attempting to make quite a few improvements, but have run into an issue, described below.
A Quick Overview
My utility’s command format is similar to command OPTIONS DEST DIR1 {DIR2 DIR3 DIR4...}
. It works by running zip -r DEST.zip DIR1
; a fairly simple process. The benefit to my utility, however, is the ability to use a predetermined file (think .gitignore
) to ignore specific files/directories, or files/directories which match a pattern.
It’s pretty simple — if the “ignorefile” exists in a target directory (DIR1, DIR2, DIR3, etc), my utility will add exclusions to the zip -r DEST.zip DIR1
command using the pattern -x some_file
or -x some_dir/*
.
The Issue
I am running into an issue with directory exclusion, however, and I can’t quite figure out why (this is probably be because I am still quite the sh novice). I’ll run through some examples:
Let’s say that I want to ignore two things in my project directory: .git/*
and .gitignore
. Running command foo.zip project_dir
builds the following command:
zip -r foo.zip project -x project/.git/* -x project/.gitignore
Woohoo! Success! Well… not quite.
In this example, .gitignore
is not added to the compressed output file, foo.zip
. The directory, .git/*
, and all of it’s subdirectories (and files) are added to the compressed output file.
Manually running the command:
zip -r foo.zip project_dir -x project/.git/* -x project/.gitignore
Works as expected, of course, so naturally I am pretty puzzled as to why my identical, but dynamically-built command, does not work.
Attempted Resolutions
I have attempted a few different methods of resolving this to no avail:
Removing
-x project/.git/*
from the command, and instead adding each subdirectory and file within that directory, such as-x project/.git/config -x project/.git/HEAD
, etc (including children of subdirectories)Removing the backslash before the asterisk, so that the resulting exclusion option within the command is
-x project/.git/*
Bashing my head on the keyboard in angst (I’m really surprised this didn’t work, it usually does)
Some notes
My utility uses
/bin/sh
; I would prefer to keep it that way for maximum compatibility.I am aware of the
git archive
feature — my use of.git/*
and.gitignore
in the above example is simply as an example; my utility is not dependent on git nor is used exclusively for projects which are git repositories.
Advertisement
Answer
I suspected the problem would be in the evaluation of the generated command, since you said the same command when executed directly did right.
So as the comment section says, I think you already found the correct solution. This happens because if you run that variable directly, some things like globs can be expanded directly, instead of passed to the command. And arguments may be messed up, depending on the situation.
Yes, in that case:
eval $COMMAND
is the way to go.