Reputation: 437
checkcommand() {
$1
}
checkcommand "which git || apt install git"
it will fail. How can I make it work and get the output?
Upvotes: 0
Views: 68
Reputation: 295659
Don't try to run a single string as if it were a command -- pass an explicit argument list instead. That gives you the flexibility of picking whichever usage mode works for you:
## first, define your function as:
checkcommand() {
"$@" # expands to "$1" "$2" "$3" ...etc, for all arguments that actually exist
}
## then, you can pass it any simple command...
type git || checkcommand apt install git
## ...or you can use it with eval...
checkcommand eval "type git || apt install git"
## ...or you can pass it a function with an argument list...
installPkg() { for pkg; do type "$pkg" || apt install "$pkg"; done; }
checkcommand installPkg git tig gcc
## ...or you can tell it to invoke a whole new shell instance...
checkcommand sh -c 'type git || apt install git'
For a detailed description of why treating a string as if it were a command is doomed to fail (in sufficiently complex use cases), see BashFAQ #50.
Upvotes: 1
Reputation: 2399
You just need to wrap the string in eval
keyword
checkcommand() {
eval "$1"
}
Quoting it ("$1"
, not $1
) ensures that the exact string is evaluated as code; otherwise, it gets split into words, each word is expanded as a glob, and the resulting words are concatenated back together; if you're lucky, this didn't change the meaning of your command -- but one may not always be lucky, so it's always best to quote your expansions unless you explicitly know why you're leaving them unquoted in any contrary case.
See the man page for POSIX eval
.
Upvotes: 3
Reputation: 2498
I'm going to suggest an alternative approach, I acknowledge doesn't answer directly.
I suggest this approach because it can be complex to pass command & args and aggregated groups of commands & args to another function to be executing and checked.
Instead a simpler approach is execute your commands and then run a check function after that, e.g.
check_error()
{
lasterr=$?
msg="$*"
if [ "${lasterr}X" != "0X" ];
then
echo "command failed, errcode ${lasterr}, $msg"
exit 1
fi
}
...
which git || apt install git
check_error "git failed"
... note that check_error
function must be the next statement immediately after the commands you wish to check.
Upvotes: 0