{"id":617,"date":"2022-08-30T15:04:20","date_gmt":"2022-08-30T15:04:20","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2013\/11\/09\/bash-getopt-command-returns-its-own-parameters-instead-of-command-line-parameters-collection-of-common-programming-errors\/"},"modified":"2022-08-30T15:04:20","modified_gmt":"2022-08-30T15:04:20","slug":"bash-getopt-command-returns-its-own-parameters-instead-of-command-line-parameters-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2022\/08\/30\/bash-getopt-command-returns-its-own-parameters-instead-of-command-line-parameters-collection-of-common-programming-errors\/","title":{"rendered":"BASH getopt command returns its own parameters instead of command line parameters-Collection of common programming errors"},"content":{"rendered":"<p>I am creating a BASH script and working with the BASH <code>getopt<\/code> command to parse command line arguments. Instead of returning the arguments provided on the command line, <code>getopt<\/code> returns the arguments that were supplied to the <code>getopt<\/code> command. I am not sure what could be going on, as the code that I have was working perfect, and seemingly out of nowhere, it has stoped working correctly (and no, I haven&#8217;t updated anything or changed any code or environment settings). I can&#8217;t use <code>getopts<\/code> (with the extra &#8216;s&#8217;) because it is, for some unknown reason, not installed on the machine that will be running this script.<\/p>\n<p>Even though the script is supplied with zero command line arguments, the getopt command is for some reason returning all of the arguments that I have supplied, minus the <code>-o<\/code> flag, instead of the expected <code>--<\/code> value indicating the end of the options. The code that I have is as follows:<\/p>\n<pre><code>SHORT_OPTS=\":hvso:l:d:n:p:t:\"\nLONG_OPTS=\"help,version,submit-job,output:,library:,job-dir:\"\nLONG_OPTS=\"${LONG_OPTS},num-nodes:,num-procs:,max-time:\"\nOPTS=$(getopt -o \"${SHORT_OPTS}\" -l \"${LONG_OPTS}\" -a -n \"${PROG_NAME}\" -- \"${@}\")\n\n# Check for invalid command line options and arguments\nif [[ ${?} -ne ${SUCCESS} ]] ; then\n    echo -e \"${PROG_NAME}: error: Invalid option or argument\\n\" &gt;&amp;2\n    usage ; exit ${FAILURE}\nelse\n    echo \"BEFORE $@\"\n    eval set -- ${OPTS}\n    echo \"AFTER $@\"\nfi\n\n# Process command line options and their arguments\nwhile true ; do\n    case \"${1}\" in\n        -h | --help) \n            # Display script usage information and exit\n            usage ; exit ${SUCCESS} ;;\n        -v | --version) \n            # Display script version information and exit\n            echo \"${PROG_NAME} v${PROG_VERSION}\" ; exit ${SUCCESS} ;;\n        -s | --submit-job) \n            # Enable automatic submission of the Moab job\n            JOB_AUTO_SUBMIT=\"${PREF_YES}\" ; shift 1 ;;\n        -o | --output) \n            # Set the base name for output file names\n            TARGET=\"${2}\" ; shift 2 ;;\n        -l | --library) \n            # Set the library to use for NWChem atomic configurations\n            NW_LIB=\"${2}\" ; shift 2 ;;\n        -d | --job-dir) \n            # Ensure the specified directory for the Moab job exists\n            if [[ -e \"${2}\" ]] ; then\n                JOB_WORK_DIR=$(resolvePath \"${2}\") ; shift 2\n            else\n                echo -e \"${PROG_NAME}: error: -d ${2}: No such directory\\n\"\n                usage ; exit ${FAILURE}\n            fi ;;\n        -n | --num-nodes) \n            # Ensure the number of compute nodes is greater than zero\n            if positiveInt \"${2}\" ; then\n                JOB_NODES=\"${2}\" ; shift 2\n            else\n                echo -n \"${PROG_NAME}: error: -n ${1}: Number of \"\n                echo -e \"job nodes must be a positive integer\\n\"\n                usage ; exit ${FAILURE}\n            fi ;;\n        -p | --num-procs) \n            # Ensure the number of processors per node is greater than zero\n            if positiveInt \"${2}\" ; then\n                JOB_PROCS=\"${2}\" ; shift 2\n            else\n                echo -n \"${PROG_NAME}: error: -p ${2}: Number of \"\n                echo -e \"processors per node must be a positive integer\\n\"\n                usage ; exit ${FAILURE}\n            fi ;;\n        -t | --max-time) \n            # Ensure the maximum job runtime is in the correct format\n            if [[ \"${2}\" == [0-9][0-9]:[0-9][0-9]:[0-9][0-9] ]] ; then\n                JOB_MAX_TIME=\"${2}\" ; shift 2\n            else\n                echo -n \"${PROG_NAME}: error: -t ${2}: Invalid time \"\n                echo -e \"format, please use hh:mm:ss format\\n\"\n                usage ; exit ${FAILURE}\n            fi ;;\n        --) \n            # No more options to process\n            shift ; break ;;\n    esac\ndone\n\n# Check to see if POTCAR and CONTCAR locations were specified\nif [[ ${#} -eq 2 ]] ; then\n    # Regular expressions for identifying POTCAR and CONTCAR files\n    PCAR_REGEX=\"[Pp][Oo][Tt][Cc][Aa][Rr]\"\n    CCAR_REGEX=\"[Cc][Oo][Nn][Tt][Cc][Aa][Rr]\"\n\n    # Attempt to identify POTCAR and CONTCAR argument ordering\n    if [[ ${1} =~ ${PCAR_REGEX} &amp;&amp; ${2} =~ ${CCAR_REGEX} ]] ; then\n        POTCAR=\"${1}\" ; CONTCAR=\"${2}\" ; shift 2\n    else\n        POTCAR=\"${2}\" ; CONTCAR=\"${1}\" ; shift 2\n    fi\n# Accept exactly two or zero command line arguments\nelif [[ ${#} -ne 0 ]] ; then\n    echo \"${PROG_NAME}: error: ${#}: Invalid argument count, expected [2|0]\"\n    echo \"$@\"\n    exit ${FAILURE}\nfi\n<\/code><\/pre>\n<p>Given this code, and running the application, I get the following output:<\/p>\n<pre><code>BEFORE \nAFTER -- :hvso:l:d:n:p:t: -l help,version,submit-job,output:,library:,job-dir:,num-nodes:,num-procs:,max-time: -a -n vasp2nwchem --\nvasp2nwchem: error: 7: Invalid argument count, expected [2|0]\n:hvso:l:d:n:p:t: -l help,version,submit-job,output:,library:,job-dir:,num-nodes:,num-procs:,max-time: -a -n vasp2nwchem --\n<\/code><\/pre>\n<p>So, the code enters the <code>while<\/code> loop portion of the code, jumps to the last case, and shifts off the first <code>--<\/code>, leaving me with all of the arguments that I supplied to <code>getopt<\/code>, minus the <code>-o<\/code> flag.<\/p>\n<p>Any light that anyone could shed on this conundrum would be immensely appreciated, because it is seriously about to send me over the edge, especially since this code was functional no less than thrity minutes ago, and has now stopped working entirely!!!<\/p>\n<ol>\n<li>\n<p>I don&#8217;t see anything wrong. I have GNU <code>getopt<\/code> installed as <code>\/usr\/gnu\/bin\/getopt<\/code> (and BSD <code>getopt<\/code> in <code>\/usr\/bin<\/code>), so this script (<code>chk.getopt.sh<\/code>) is almost equivalent to the start of yours, though I do set the <code>PROG_NAME<\/code> variable. This is more or less the SSCCE (Short, Self-Contained, Complete Example) for your rather substantial script.<\/p>\n<pre><code>#!\/bin\/bash\n\nPROG_NAME=$(basename $0 .sh)\nSHORT_OPTS=\":hvso:l:d:n:p:t:\"\nLONG_OPTS=\"help,version,submit-job,output:,library:,job-dir:\"\nLONG_OPTS=\"${LONG_OPTS},num-nodes:,num-procs:,max-time:\"\nOPTS=$(\/usr\/gnu\/bin\/getopt -o \"${SHORT_OPTS}\" -l \"${LONG_OPTS}\" -a -n \"${PROG_NAME}\" -- \"$@\")\n\n# Check for invalid command line options and arguments\nif [[ ${?} -ne ${SUCCESS} ]] ; then\n    echo -e \"${PROG_NAME}: error: Invalid option or argument\\n\" &gt;&amp;2\n    usage ; exit ${FAILURE}\nelse\n    echo \"BEFORE $@\"\n    eval set -- ${OPTS}\n    echo \"AFTER $@\"\nfi\n<\/code><\/pre>\n<p>When I run it, this is the output:<\/p>\n<pre><code>$ bash -x chk.getopt.sh  -ooutput -nnumber -pperhaps -ppotato -- -o oliphaunt\n++ basename chk.getopt.sh .sh\n+ PROG_NAME=chk.getopt\n+ SHORT_OPTS=:hvso:l:d:n:p:t:\n+ LONG_OPTS=help,version,submit-job,output:,library:,job-dir:\n+ LONG_OPTS=help,version,submit-job,output:,library:,job-dir:,num-nodes:,num-procs:,max-time:\n++ \/usr\/gnu\/bin\/getopt -o :hvso:l:d:n:p:t: -l help,version,submit-job,output:,library:,job-dir:,num-nodes:,num-procs:,max-time: -a -n chk.getopt -- -ooutput -nnumber -pperhaps -ppotato -- -o oliphaunt\n+ OPTS=' -o '\\''output'\\'' -n '\\''number'\\'' -p '\\''perhaps'\\'' -p '\\''potato'\\'' -- '\\''-o'\\'' '\\''oliphaunt'\\'''\n+ [[ 0 -ne '' ]]\n+ echo 'BEFORE -ooutput' -nnumber -pperhaps -ppotato -- -o oliphaunt\nBEFORE -ooutput -nnumber -pperhaps -ppotato -- -o oliphaunt\n+ eval set -- -o ''\\''output'\\''' -n ''\\''number'\\''' -p ''\\''perhaps'\\''' -p ''\\''potato'\\''' -- ''\\''-o'\\''' ''\\''oliphaunt'\\'''\n++ set -- -o output -n number -p perhaps -p potato -- -o oliphaunt\n+ echo 'AFTER -o' output -n number -p perhaps -p potato -- -o oliphaunt\nAFTER -o output -n number -p perhaps -p potato -- -o oliphaunt\n$\n<\/code><\/pre>\n<p>This all looks correct; the options before the double dash have been split from their arguments, and the ones after the double dash are OK.<\/p>\n<p>So, it is not obvious that there&#8217;s a problem with your code. Even with an empty string as the program name, it worked OK for me.<\/p>\n<p>May be you should show the output of this much of the script on your machine?<\/p>\n<\/li>\n<\/ol>\n<p id=\"rop\"><small>Originally posted 2013-11-09 21:07:50. <\/small><\/p>","protected":false},"excerpt":{"rendered":"<p>I am creating a BASH script and working with the BASH getopt command to parse command line arguments. Instead of returning the arguments provided on the command line, getopt returns the arguments that were supplied to the getopt command. I am not sure what could be going on, as the code that I have was [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-617","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/617","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=617"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/617\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=617"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=617"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=617"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}