0

I have 8 options which are mandatory to run the script. However I am unable to pass option values after the first argument. Could you please let me know what I am doing wrong here.

 #!/usr/bin/env bash
    usage() { echo "Usage: $0 -f sample_R1.fastq -r sample_R2.fastq -hrp HISAT2_REFERENCE_PATH -g GTF_file -sp KNOWN_SPLICE_FILE -b BOWTIE2_REFERENCE.fasta -rsem_path RSEM_REFERENCE -out_path OUTPUT_PATH -h help" 1>&2; exit 1; }

while getopts ":f:r:hrp:g:s:b:rsem_path:out_path:h" opt; do
    case "${opt}" in
        f) f="$OPTARG"; shift ;; # sample_R1.fastq 
        r) r="$OPTARG"; shift ;; # sample_R2_fastq
        hrp) hrp="$OPTARG"; shift ;;    # HISAT2_REFERENCE_PATH
        g) g="$OPTARG"; shift ;;        # GTF_file
        sp) sp="$OPTARG"; shift ;; # KNOWN_SPLICE_FILE
        b) b="$OPTARG"; shift ;;        # BOWTIE2_REFERENCE
        rsem_path) rsem_path="$OPTARG"; shift ;; #RSEM Reference path
        out_path) out_path="$OPTARG"; shift ;; #Results output path
        h | *) usage ; exit;;
    esac
done

echo "f = ${f}"
echo "r = ${r}"
echo "hrp = ${hrp}"
echo "g = ${g}"
echo "sp = ${sp}"
echo "b = ${b}"
echo "rsem_path = ${rsem_path}"
echo "out_path = ${out_path}"

Results

f = ./test_data/HBR_Rep1_ERCC-Mix2_Build37-ErccTranscripts-chr22.read1.fastq
r = 
hrp = 
g = 
sp = 
b = 
rsem_path = 
out_path = 
user44552
  • 153
  • 1
  • 10

2 Answers2

3

There are a number of problems here:

  • getopts only does single-letter options, and will treat -hrp as a shorthand for -h -r -p (just like ls -la is short for ls -l -a). There is a semi-standard format for long options (that start with a double dash, e.g. ls --color), but getopts doesn't support this.

  • getopts sets the option variable (opt in this case) to the option not including the -, so your cases should look like e.g. f) instead of -f).

  • Don't use shift in the middle of the getopts loop. getopts keeps track of where it is in the argument list, and if the argument list gets shifted while it's working on it... things get very confused. Instead, use shift $((OPTIND-1)) after the loop to get rid of all of the options that've been dealt with.

  • You're not actually capturing the option values. That is, when parsing -f sample_R1.fastq, getopts will set OPTARG to "sample_R1.fastq" but you ignore that and just set f to the string "true".

  • And finally, you started the option string with ":", which tells getopts it shouldn't report errors because you'll take are of that, but you don't. Also, even without that ":", if getopts sees an option that isn't on the list, it'll run the loop with opt set to "?", so you should check for that and give the usage message in that case.

Here's my take at a corrected version:

#!/usr/bin/env bash
    usage() { echo "Usage: $0 -f sample_R1.fastq -r sample_R2.fastq -H HISAT2_REFERENCE_PATH -g GTF_file -s KNOWN_SPLICE_FILE -b BOWTIE2_REFERENCE.fasta -R RSEM_REFERENCE -o OUTPUT_PATH [-h]" 1>&2; exit 1; }

while getopts "f:r:H:g:s:b:R:o:h" opt; do
    case "${opt}" in
        f) f="$OPTARG" ;; # sample_R1.fastq 
        r) r="$OPTARG" ;; # sample_R2_fastq
        H) hrp="$OPTARG" ;;    # HISAT2_REFERENCE_PATH
        g) g="$OPTARG" ;;        # GTF_file
        s) sp="$OPTARG" ;; # KNOWN_SPLICE_FILE
        b) b="$OPTARG" ;;        # BOWTIE2_REFERENCE
        R) rsem_path="$OPTARG" ;; #RSEM Reference path
        o) out_path="$OPTARG" ;; #Results output path
        h | [?]) usage ; exit;;
    esac
done
shift $((OPTIND-1))

echo "f = ${f}"
echo "r = ${r}"
echo "hrp = ${hrp}"
echo "g = ${g}"
echo "sp = ${sp}"
echo "b = ${b}"
echo "rsem_path = ${rsem_path}"
echo "out_path = ${out_path}"

Note that if you want to give an error message if some options were omitted, you need to check that all of those variables got set. Something like if [ -z "$f" ] || [ -z "$r" ] ||...

Gordon Davisson
  • 118,432
  • 16
  • 123
  • 151
0

You don't need the "-" in the case statement and so -f should f -r r etc.

Raman Sailopal
  • 12,320
  • 2
  • 11
  • 18