Nick Grealy
Nick Grealy

Reputation: 25872

Shell script > double quote a parameter, ONLY if it exists

Background: we've currently got a project, which requires cloning multiple git repositories into a single parent folder. I'm attempting to write a script, so that I can run git operations, across all subdirectories, to make it easier to manage (e.g. ./gitall.sh status / add / reset / commit -m "Foobar" / push / etc.

The script is working well for all operations, until I attempt to perform a ./gitall.sh push

I receive the error fatal: remote part of refspec is not a valid name in for each directory, because the effective command is git -C somedir push "" "" "" "" (git borks at the trailing double quotes). N.B. the parameters need to be double quoted, so that it captures parameters with spaces.

gitall.sh

find ./repo-* -type d -depth 0 -exec bash -c "git -C {} \"$1\" \"$2\" \"$3\" \"$4\" \"$5\"" \;

Is there anyway to double quote a parameter, ONLY if it exists? (or anyway to tell git to ignore the trailing double quotes?)

Upvotes: 1

Views: 79

Answers (3)

Sir Athos
Sir Athos

Reputation: 9877

The right way to pass an unknown number of parameters in bash is to use "$@". Further, you don't need to explicitly call bash, because it will complicate the way you need to quote the parameters.

This will automatically quote all parameters:

#!/bin/bash
find ./repo-* -type d -depth 0 -exec git -C {} "$@" ';'

Going one more step, there is no need to call find if all you want is directory entries in the current level. The / at the end of the matching pattern will select only directories:

#!/bin/bash
for d in repo-*/; do
    [ -d "$d" ] && git -C "$d" "$@"
done

(Note that if you don't have any directories that match the pattern, the loop will execute once with the literal argument repo-*/; the [ -d "$d" ] will guard against git being called in this case).

Lastly, you may want to consider using Google's repo tool instead of your own solution for managing multiple git repos. It's very powerful and easy to use.

Upvotes: 3

Schwern
Schwern

Reputation: 164859

The problem is you're passing in extra arguments to git push. Each "" is passed by the shell to git which then thinks its getting 7 arguments, but the last 4 are empty strings.

What you're looking for is "$@". "$@" is equivalent to "$1" "$2" ...

There's no need for all the extra quoting, nor the bash -c. "$@" will be expanded in the shell script.

Also note that invocation of find won't work with GNU find, so use the full path to BSD find.

#/bin/sh

/usr/bin/find ./repo-* -type d -depth 0 -exec git -C {} "$@" \;

Upvotes: 2

jthill
jthill

Reputation: 60295

You're after "$@", and there's better ways to do what you're doing:

find -name .git -prune -execdir git "$@" \;

and you can add -maxdepth 1 or whatever to limit the find command's spelunking further.

Upvotes: 1

Related Questions