0

I am trying to write bash script which will read multiple filenames and a target directory, which is optional.

./myfile -t /home/users/ file1 file2

I have tried the following code, but I am not able to handle different scenarios mentioned below:

while getopts "t:" opt; do
  case $opt in
    t)
      echo "-t was triggered, Parameter: $OPTARG"
      ;;
    \?)
      echo "Invalid option: -$OPTARG"
      exit 1
      ;;
    :)
      echo "Option -$OPTARG requires an argument."
      exit 1
      ;;
  esac
done

But the code should handle different scenarios like: ./myfile file1 file2 -t /home/users/, ./myfile file1 -t /home/users/ file2 file3, ./myfile file1 file2 file3 file4 and should be able to read the files.

Sagar Jogadia
  • 1,330
  • 1
  • 16
  • 25
  • 1
    "Traditional" unix command syntax requires that options come before positional parameters, and this is what `getopts` supports. If you want to allow options later in the sequence, you need to do the parsing yourself. – Gordon Davisson May 27 '19 at 19:01

2 Answers2

1

Using a while loop to read and shift the arguments might be easier in this case. In the example below the arguments are looped through to look for the string -t in which case the arguments array is shifted one step and the now nr 1 index is supposed to be the optional homedir. In all the other cases the item is moved to another array called files.

#! /bin/bash

files=()
homedir=
while (( $# > 0 )); do
    case "$1" in
        -t )
            shift
            homedir="$1"
            ;;
        * )
            files+=("$1")
        ;;
    esac
    shift
done
echo "${files[@]}"
echo "$homedir"
Olli K
  • 1,720
  • 1
  • 16
  • 17
0

After your while loop, you need to shift out any options and their arguments. This works even if there aren't any flags/flag arguements.

shift $(($OPTIND - 1))

Then the rest of the arguments are available in "$@" and can be dealt with in any of the usual ways. For example:

for arg in "$@"
do
    something_with "$arg"
done

For some more information, see my answer here.

Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439