26

This question already has an answer here:

Found this in an obfuscated malicious shell script, beginning with:

${!#}${*^} <<<...

Could not find any reference to ${!#}, but when echo'd, it outputs -bash. Is this a secret referene to the running shell? Why there is an extra dash then?

Thanks!

marked as duplicate by Jesse_b, 200_success, X Tian, garethTheRed, Philip Couling May 24 at 14:39

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 3
    In "shell scripting", that will expand to the PID of the last background command. In bash (and only in bash), ${!#} is the last positional parameter obtained via "Indirect Expansion" (the ${!var} syntax) of the the $# variable. – mosvy May 23 at 14:07
  • 4
    @mosvy That looks like an answer, not a clarification of the question. As you point out, it includes information missing from the current answer, which is exactly why the system allows multiple answers to one question. – IMSoP May 23 at 14:31
  • Regarding the extra dash itself, refer to this answer: superuser.com/a/278865/560377 – Phlarx May 23 at 16:27
35

This answer is bash-specific, because you tried the echo in bash. Not all shells behave the same.

In bash, if $var1 is foo, then ${!var1} is the same as $foo. The ! is indirect expansion: it causes bash to retrieve from the given variable a variable name (foo) instead of a value.

Now replace var1 with #$# is the number of arguments.  If $# is 0, ${!#} is $0.  If $# is 4, ${!#} is $4.  In other words, ${!#} is the last positional parameter, no matter how many there positional parameters there are.

If there are no positional parameters, $# is 0, so the result is $0, which is the name of the shell or script (reference). In your case, that was bash (plus a leading - meaning that it's a login shell).

Quick test:

$ echo ${!#}
-bash

$ set the quick brown fox

$ echo ${!#}
fox
  • 19
    Your answer only applies to bash, but you fail to mention that. In all the other shells, ${!#} will expand to the PID of the last background command ($!) with a empty string removed from the beginning (the ${var#pat} form of parameter expansions). – mosvy May 23 at 13:55
  • 2
    Comments are indeed for clarifying answers; while it's possible to assume bash, given the text in the question, it's certainly reasonable to (collaboratively!) edit this answer to indicate shell-specific behavior. – Jeff Schaller May 23 at 17:58

Not the answer you're looking for? Browse other questions tagged or ask your own question.