0

I have a bash function:

function some_function()
{
   $*
}

I call this function like this:

some_function "cal 2014"

Why do I get a "cal 2014": not found error?

But it works if I call:

some_function "cal"
2
  • Because the shell is trying to find a command named 'cal 2014'. Perhaps you are expecting the shell to behave as if you typed eval $*. Commented Apr 23, 2015 at 16:50
  • 4
    What shell and what version is this? Did you use $* or did you use "$*"? That behavior sounds like "$*" not $* to me. Commented Apr 23, 2015 at 17:01

2 Answers 2

2

Let's examine the various behaviors here for a minute.

$ # Helper function to show some useful details.
$ c ()
{
    printf 'argc: %s\n' "$#";
    printf 'argv: %s\n' "$@"
}
$ # The function in question.
$ t ()
{
    printf '$*\n';
    c $*;
    $*;
    printf '"$*"\n';
    c "$*";
    "$*";
    printf '$@\n';
    c $@;
    $@;
    printf '"$@"\n';
    c "$@";
    "$@"
}

If we call the function like this t "echo foo" we get

$*
argc: 2
argv: echo
argv: foo
foo
"$*"
argc: 1
argv: echo foo
-bash: echo foo: command not found
$@
argc: 2
argv: echo
argv: foo
foo
"$@"
argc: 1
argv: echo foo
-bash: echo foo: command not found
  • The $* and $@ versions expand to two arguments and work correctly.
  • The "$*" and "$@" versions expand to a single argument and fail.

What if we call it like this t echo foo?

$*
argc: 2
argv: echo
argv: foo
foo
"$*"
argc: 1
argv: echo foo
-bash: echo foo: command not found
$@
argc: 2
argv: echo
argv: foo
foo
"$@"
argc: 2
argv: echo
argv: foo
foo
  • This time the $*, $@ and "$@" versions all expand to two arguments and work.
  • Only the "$*" version expands to a single argument and fails.

Ok. That makes sense since $* expands the arguments as individual (unquoted) words; "$*" expands to a single (quoted) word; $@ expands like $*; and "$@" expands to individual (quoted) words.

What about if we try this t echo "foo bar"?

$*
argc: 3
argv: echo
argv: foo
argv: bar
foo bar
"$*"
argc: 1
argv: echo foo bar
-bash: echo foo bar: command not found
$@
argc: 3
argv: echo
argv: foo
argv: bar
foo bar
"$@"
argc: 2
argv: echo
argv: foo bar
foo bar

Now things get interesting.

  • $* expands to three arguments. (Ok. I did say "individual (unquoted) words)" before.)
  • "$*" expands to one argument. (Right, "single (quoted) word".)
  • $@ expands to three arguments. (Right, same as $*.)
  • But "$@" expands to two arguments and keeps our internal space correctly. (As I said "individual (quoted) words)".)

This is why, in general, you always quote variables and almost always want to use the @ expansions over the * expansions. Because they handle spaces and metacharacters correctly.

Ultimately though we didn't reproduce your problem when using $* directly. Are you sure you didn't use "$*" instead?

Sign up to request clarification or add additional context in comments.

2 Comments

There are a lot of semicolons in there that don't look like they're necessary. Did Bash flatten your history and insert them?
@JonathanLeffler The ones in the function definitions? Yeah, those came from type <fun>.
0

If you quote "cal 2014" like that, you are making it into a single parameter. You may want some_function "cal" "2014" and see if that works better for you. That said, I was not able to reproduce the error you describe.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.