1

I know if I have a command ./run -c -p '$' -s 10 file.txt
I can write bash script like this

while read line; do 
   # ...
done < $6

But what if the command may or may not have one/some options, maybe look like this

./run -p '$' -s 10 file.txt

or this

./run '$' -s 10 file.txt

Then how can I get the file name in the script?

mklement0
  • 382,024
  • 64
  • 607
  • 775
LuckyLast
  • 61
  • 2
  • 10
  • Note that your last snippet is nonstandard in that most (POSIX-compliant) utilities expect _all_ option arguments _before_ the non-option (filename) ones; in other words: most utilities would interpret _all 3 arguments_ in your last snippet as non-option (filename) arguments. – mklement0 May 26 '14 at 02:14

3 Answers3

3

If the file name always comes at the end of the list of arguments, you can use "${@: -1}" to select the last argument. Taken from: https://stackoverflow.com/a/1854031/3565972

Eg.:

while read line; do 
   ...
done < "${@: -1}"
Community
  • 1
  • 1
savanto
  • 4,470
  • 23
  • 40
  • 2
    You need the space, otherwise the `:-` gets interpreted as "default value of 1". – Kevin May 25 '14 at 23:29
  • @Kevin Thanks for catching that! – savanto May 25 '14 at 23:31
  • May I know what if my filename is not at the end of the list of arguments? Than what should I refer to that filename? Thanks. – LuckyLast May 26 '14 at 05:56
  • @LuckyLast If you don't know the position of your filename, you can either pick it out of the arguments using something like a regex (eg. search for a string that looks like `*.txt`); you could use a flag to specify that a filename follows (eg. `-f file.txt`); or you could go with a robust method like `getopts` as [suggested by user2303197](http://stackoverflow.com/a/23861378/3565972) – savanto May 26 '14 at 06:03
  • @savanto, Thank you for your response. but what if the command like this : ./run filename -c -p '$' -s 10, that getopts doesn't working on it. – LuckyLast May 26 '14 at 06:09
  • @LuckyLast Actually, it looks like `getopts` will stop processing options if they are not a flag that looks like `-x`. So I think the simplest way would be to use `getopts` and add an option `-f` which would precede your filename. You can use the `getopts` solution provided by user2303197, add a `-f` case, and get the filename from `$OPTARG`. Then your call would be `./run -f filename -c -p '$' -s 10`. – savanto May 26 '14 at 06:15
3

Use getopts to process the options (that also allows them to be in arbitrary order):

#!/usr/bin/env bash

while getopts cp:s: option; do
    case $option in
    c)
        echo "-c used"
        ;;
    p)
        echo "-p used with argument $OPTARG"
        ;;
    s)
        echo "-s used with argument $OPTARG"
        ;;
    *)
        echo "unknown option used"
        exit 1
        ;;
    esac
done

shift $(( OPTIND - 1 ));

echo "Arguments left after options processing: $@"

Now if you run this:

$ ./test.sh -c -p '$' -s 10 file.txt
-c used
-p used with argument $
-s used with argument 10
Arguments left after options processing: file.txt
user2303197
  • 1,271
  • 7
  • 10
0

If you want to get the filename in your script ./run. Then you can just use $# to get the total of the parameters. And so you can write as below:

eval filename=\$$#

If you just want to get the filename from a line like this: ./run ** ** ** ** file.txt

You can just use awk as below:

line="./run ** ** ** ** file.txt"
echo $line | awk '{print $NF}'

Good Luck!

Nancy
  • 1,183
  • 1
  • 7
  • 17