2

I would like my bash script to take either 2 or 3 arguments with the last argument always being the input file to open. So the index of argument should depend on how many arguments provided. I know this can be realized by if statement, like:

if [ $# -eq 3 ]; then
  INFILE=$3
elif [ $# -eq 2 ]; then
  INFILE=$2
fi

..open file to read...

However I was hoping this to be done by a one liner which would look like this:

INFILE=$($#)

It does not work though. Same thing with INFILE=$"$#". Is it possible to specify index of argument directly with "$#"

ddd
  • 4,665
  • 14
  • 69
  • 125

3 Answers3

3

Try using INFILE="${@: -1}" to get the last argument.

Rickkwa
  • 2,197
  • 4
  • 23
  • 34
  • I've had this in my arsenal for some time too, but I've never understood why it works. Can you explain? – ghoti Aug 18 '14 at 20:23
1

You're seeing a well known limitation in shell. :-)

You could get the last argument by stepping through the existing arguments:

#!/bin/bash

while [ ! -z "$2" ]; do
  shift
done

echo "Last argument: $1"

In Bourne (non-Bash) shell, you could do this with eval, which is evil:

#!/bin/bash

eval "echo \"Last argument: \$$#\""

If you don't need portability outside bash, you can also use the @ array:

#!/bin/bash

echo "Last argument: ${@: -1}"
ghoti
  • 45,319
  • 8
  • 65
  • 104
1

You're trying to do indirect referencing of an array, so ${!#} would also work.

Beggarman
  • 866
  • 5
  • 7