Goal and context
I am writing a bash script (called foreach_repo) that should execute the passed parameters as a shell command, e.g.:
foreach_repo hg status
should execute the command hg status. (It does this on a complicated nested structure of repositories, I have no control over this structure, but I need to batch operate on them quite often).
This type of command is similar to sudo and other 'higher-order' commands; for example sudo hg status would in turn execute hg status with superuser rights.
Internally, my script does the following (given a feed of repository paths on stdin, created by another part of the script - irrelevant to this question):
while read repo do
container="$repo/.."
cd $base/$container
$@
done
Where $@ is meant to interpret the passed arguments as the command to be executed in the repository.
Execution
This approach works fine for simple commands, for example
foreach_repo hg status
will correctly return the status list of every repository in the structure. However, more complicated commands (with escapes, quotes ...) are messed up. For example, when I try
foreach_repo hg commit -m "some message"
I get
abort: message: no such file or directory
Because the quotes were stripped off, the actual command executed was:
hg commit -m some message
Attempted solutions
Manually escaping the quotes, or the entire command to be passed, has no effect, neither has using $* instead of $@. However, commands like sudo can handle this type of situation, that is:
sudo hg commit -m "some message"
would actually (and correctly) execute
hg commit -m "some message"
How can I accomplish the same behavior?