bashgetopt

how to make an argument optional in getopts bash


I want to make an argument as optional in getopt bash so that if the user didn't specify it, then it still runs without killing the program. How can i do that. Here is my previous code

while getopts ":l:q:s:e:hg:" opt; do
  case $opt in
    l)
      lincRNAfasta=$OPTARG
    ;;
    q)
      query_species=$OPTARG
      ;;
    s)
      subject_species=$OPTARG
      ;;
    e)
      subject_gff=$OPTARG
      ;;
    h)
      echo "USAGE : open script in text editor"
      exit 1
      ;;
    g)
      subject_genome=$OPTARG
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      exit 1
      ;;
    :)
      echo "Option -$OPTARG requires an argument." >&2
      exit 1
      ;;
  esac
done

Solution

  • Sorry, had to update my answer, I misunderstood the question.

    I was looking at the documentation for getopts.c which does support ::

    But the code that you have works whether I specify 1, 2, or 3 arguments, and in any order.

    If it is exiting with an error one reason could be that the variables need to be defined:

    #! /bin/bash
    lincRNAfasta=
    query_species=
    subject_species=
    subject_gff=
    subject_genome=
    
    help='''
      USAGE : open script in text editor
        -l lincRNAfasta
        -q query_species
        -s subject_species
        -e subject_gff
        -g subject_genome
    '''
    
    while getopts ":l:q:s:e:hg:" opt; do
      case $opt in
        l)
          lincRNAfasta=$OPTARG
        ;;
        q)
          query_species=$OPTARG
          ;;
        s)
          subject_species=$OPTARG
          ;;
        e)
          subject_gff=$OPTARG
          ;;
        h)
          printf "$help"
          exit 1
          ;;
        g)
          subject_genome=$OPTARG
          ;;
        \?)
          echo "Invalid option: -$OPTARG" >&2
          exit 1
          ;;
        :)
          echo "Option -$OPTARG requires an argument." >&2
          exit 1
          ;;
      esac
    done
    
    echo "doing something else"
    
    if [ -z "$lincRNAfasta" ];then
        echo "its empty"
        echo "lincRNAfasta: $lincRNAfasta"
        echo
    else
        echo "not empty"
        echo "lincRNAfasta: $lincRNAfasta"
        echo
    fi
    
    if [ -z "$query_species" ];then
        echo "its empty"
        echo "query_species: $query_species"
        echo
    else
        echo "not empty"
        echo "query_species: $query_species"
        echo
    fi
    
    if [ -z "$subject_species" ];then
        echo "its empty"
        echo "subject_species: $subject_species"
        echo
    else
        echo "not empty"
        echo "subject_species: $subject_species"
        echo
    fi
    
    if [ -z "$subject_gff" ];then
        echo "its empty"
        echo "subject_gff: $subject_gff"
        echo
    else
        echo "not empty"
        echo "subject_gff: $subject_gff"
        echo
    fi
    
    if [ -z "$subject_genome" ];then
        echo "its empty"
        echo "subject_genome: $subject_genome"
        echo
    else
        echo "not empty"
        echo "subject_genome: $subject_genome"
        echo
    fi
    
    
    # do something once variables have been set
    # any variable not set will be empty
    
    echo "doing something else"
    

    Output:

    bob@squids:~/Desktop$ ./1.sh -h
    
      USAGE : open script in text editor
        -l lincRNAfasta
        -q query_species
        -s subject_species
        -e subject_gff
        -g subject_genome
    bob@squids:~/Desktop$ ./1.sh -s a -g h -e e -q q
    doing something else
    its empty
    lincRNAfasta: 
    
    not empty
    query_species: q
    
    not empty
    subject_species: a
    
    not empty
    subject_gff: e
    
    not empty
    subject_genome: h
    
    doing something else
    bob@squids:~/Desktop$ ./1.sh -s a -g h -e e
    doing something else
    its empty
    lincRNAfasta: 
    
    its empty
    query_species: 
    
    not empty
    subject_species: a
    
    not empty
    subject_gff: e
    
    not empty
    subject_genome: h
    
    doing something else
    bob@squids:~/Desktop$ ./1.sh -s a -e e -g 123
    doing something else
    its empty
    lincRNAfasta: 
    
    its empty
    query_species: 
    
    not empty
    subject_species: a
    
    not empty
    subject_gff: e
    
    not empty
    subject_genome: 123
    
    doing something else
    

    Or instead of initializing the variables as empty, you could initialize them as a string like "NOTSPECIFIEDONSTART". And when starting the script you could pass an empty string like -g ''