This question already has an answer here:

If I ask bash to echo the -1th argument it prints hb1:

echo $-1

Why? What is it accessing?

marked as duplicate by muru, mosvy, terdon bash Jul 25 at 22:06

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.

  • 2
    $- gets the current shell options (which is apparently "hb"). What did you expect it to do? – Gordon Davisson Jun 22 at 19:21
  • I thought it might loop round like some arrays do. Thanks. – Neil Jun 22 at 19:23

You are not asking it to print the 1st argument, that would be: $1.

What you are asking for is a special parameter:


($-, a hyphen.) Expands to the current option flags as specified upon invocation, by the set builtin command, or those set by the shell itself (such as the -i option).

So your options are: hb

Then you see the 1 you've added is printed afterwards (hence hb1).

If you are looking to get the last argument (Not sure if that is what you meant by -1 argument), you can use Shell Parameter Expansion in the following form:

$ set -- one two three
$ echo "${@: -1}"
  • 8
    ${!#} is also the value of the last parameter, using indirect expansion. – glenn jackman Jun 22 at 19:30
  • 2
    Hmmm: ${@:~0} and eval echo \$$# are also the last argument. :-) – Isaac Jun 22 at 20:32
  • @Isaac If you're lucky, that's true. If IFS contains any digits in the value $# expands to, not so much. Always safer to quote; eval "echo \"\$$#\"" is more reliable. To see the failure for yourself: IFS=1234567890; set -- one two three; eval echo \$$# only outputs $. – Charles Duffy Jun 23 at 20:10
  • @CharlesDuffy Yes, you are correct, my mistake. But it is also required to allow positional parameters at position 10 and up. For a really reliable solution add {} : IFS=1234567890; set -- {a..w}; eval echo \"\$\{"$#"\}\" ;-) – Isaac Jun 23 at 20:27

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