1

Currently I'm executing my bash script with unnamed filename parameters:

./exec.sh filename1 filename2 

What I want to achieve is to add one named parameter s

./exec.sh filename1 filename2 -s bla 

where s is an optional argument stands for "suffix" and if exists, has to be appended to all filenames inside script.

I have a part in bash script that looks like:

for param in "$@"
do
    file_name=$(< $files/$param)

As far as I know, I should use getopt but not sure about its syntax.

How can I implement to get optional -s parameter from the arguments list?

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
demonoid
  • 318
  • 3
  • 13
  • 40
  • You should use `getopts` instead of `getopt`, you can find a lot of examples in SO. It has a few limitations: 1) the options need to be specified **before** the arguments (for ex. `./exec.sh -s bla filename). 2) no long options (for ex. `./exec --suffix`). If you can't live with that then you'll have to parse the arguments and implement the logic yourself. – Fravadona Dec 07 '21 at 09:28
  • Does this answer your question? [How do I parse command line arguments in Bash?](https://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash) – Aserre Dec 07 '21 at 09:41
  • @Fravadona as far as I can tell, `getopt` seems to be more powerful than `getopts` (see the 2nd answer in the dupe I linked) – Aserre Dec 07 '21 at 09:46
  • @Aserre `getopt` is an external binary in which you can't rely too much; and it appears to be a little broken (not sure about the specific reason) – Fravadona Dec 07 '21 at 09:59
  • 1
    @Fravadona the only drawback I see against `getopt` is the lack of support for OSX (though you can still manually install it). Otherwise, I don't know why you call it `a little broken` – Aserre Dec 07 '21 at 10:23
  • @Aserre I read it somewhere in SO; my memory might be failing me though – Fravadona Dec 07 '21 at 10:27
  • @demonoid is it a suffix, a prefix, or a base directory? the difference is as follows: `"filename$suffix"` `"${prefix}filename"` `"$directory/filename"` – Fravadona Dec 07 '21 at 15:44
  • IMO, it's a lot easier to parse the arguments (and easier for an interactive user to type) if you rely on `=` in the option. eg, `./exec.sh filename1 filename2 s=bla`. And, if you control the environment and aren't worried about pollution, you can even make the call `s=bla ./exec.sh filename1 filename2` and your parsing issues pretty much evaporate. – William Pursell Dec 07 '21 at 15:56
  • I'll second what @Aserre said. If you're only going to run a script on Linux, `getopt` is a lot more powerful. It can parse both `--long` and `-s` short options, for one. The drawback is that it's Linux-specific, not POSIX, so it won't work on macOS. – John Kugelman Dec 07 '21 at 17:33

1 Answers1

0

I agree with @Fravadona, using getopts may be the best choice, but try this as an individual logic workaround.

_Note: By this, you are able to set the '-s <YOUR_SUFFIX_PATH>' anywhere in the command line.

#!/bin/bash

# Your first option variable to catch.
_opt1='-s'

# Indexing variable you don't need to modify.
_n=0

# Create an array from all arguments.
_inputs=( `echo $@` )

# After this for loop block you can call the argument assigned to -s by
# calling the "${_arg1}" variable (if found any).
for _i in "${_inputs[@]}" ;do
  if [ "${_i}" == "${_opt1}" ] ;then
    _opt1arg_index=$(( $_n+1 ))
    _arg1="${_inputs[$_opt1arg_index]}"
  fi
  _n=$(( _n+1 ))
done

# Note: If you need to pars the script arguments in your code use the 
# following 'while' block to avoid reading the '-s' and the argument assigned to it.
while [ ! "$*" == '' ] ;do
  if [ "${1}" == "${_opt1}" ] ;then
    shift 2
  fi

### Put your code from here...

  # example
  echo "${_arg1}/${1}"

### ... To here

  shift
done

Test by:

test-script.sh file1 file2 -s /usr/local file3 file4 

Output should be:

/usr/local/file1
/usr/local/file2
/usr/local/file3
/usr/local/file4
Vab
  • 412
  • 1
  • 11