1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Processing command line options & parameters in a batch file

Discussion in 'T&T - Scripting' started by nchernoff, Jun 4, 2008.

  1. nchernoff

    nchernoff Administrator
    Staff Member

    Joined:
    May 16, 2008
    Messages:
    42
    Likes Received:
    2
    Migrated From JP Software Wiki

    Overview

    There are often times one wishes to process command line options and parameters in a consistent way, and not duplicate parsing in every bath file. GetOpt is a common and freely available option parser and this batch file attempts to mimic a few of it's basic functions within the limitations of TakeCommand.

    There are two main categories of command line items.

    1. Program Parameters. These are inputs for the progam and are entered in on the command line without switch characters. For example, the command "copy a b" has two parameters, a and b.
    2. Program Switches. These typically change the way the command works. They are usually prefaced with a dash (-) or a slash (/). For example, the command "copy /q a b" has one boolean switch. Switches may also have values associated with them, so the command "copy /q /s:1 a b" is valid.
    The usage of GetOpt.btm is fairly simple.
    • If you wish to see a lot of debug information on what's going on, execute "set debug=1" before running.
    • Call getopt.btm in your batch file by executing: call GetOpt.btm %$
    • OPTION_x will be set for each option where x is the option name. If the option equals a value, it will be set that value, if not it will be set to 1.
    • PARAM_x will be a sequential number each equal to the parameter value.
    • PARAM_0 is a special case and will equal the number of parameters entered
    • It is highly recommended that your batch file by enclosed by "SetLocal" and "EndLocal" commands. This will prevent the variables set in GetOpt from living after your program has terminated. You could also add:
      unset getopt* OPTION_* PARAM_*
      at the end of your program to clean up the variables that are set.


    I hope that the following example may help illustrate.

    Examples:
    Code:
    BatchFile.btm /a /b:22 /longopt Parm1 Parm2 /quotedArg:"long quoted arg"
       - OPTION_a will equal 1.
       - OPTION_b will equal 22
       - OPTION_quotedArg will equal "long quoted arg"
       - OPTION_longopt will eqal 1.
       - PARAM_1 will equal Parm1
       - PARAM_2 will equal Parm2
       - PARAM_0 will be set to the number of parms, so 2 in this case
    So, as an example, to process all items listed on the command line you could:

    Code:
    call GetOpt.btm %$
    do i=1 to %PARM_0 by 1
      echo Processing %PARM_$i
      gosub ProcessParm
    enddo
    Or, to perform an action based on a boolean switch you could:

    Code:
    call GetOpt.btm %$
    iff defined %OPTION_v then
      gosub DisplayVerion
    endiff
    
    I would appreciate any comments or suggestions I could use to improve this program.

    Michael Fross
    michael _at_ fross _dot_ org


    GetOpt.btm

    Code:
    @echo off
    :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    :: GetOpt - Process command line options
    :: 
    :: Michael Fross
    :: [email]michael@fross.org[/email]
    :: [url]http://fross.org[/url]
    ::
    :: This program scans the command line sent to it and sets various 
    :: environment variables that coorespond to the settings.
    ::
    :: It sets an OPTION_arg variable for each arg on the command line.
    :: If a switch, the env var is set to 1.  If a value is given via the colon sign,
    :: it's set to that value.  Note, there can not be any white space around the ':'
    ::
    :: Use "If defined OPTION_arg" or "If %OPTION_arg eq value" to test for options
    ::
    :: It also sets a parameter variable for each paramater entered: PARAM_1 to PARAM_n
    :: PARAM_0 is a special value that contains the number of PARAMs.  Useful for looping
    :: through all of them.  For example, do i = 1 to %PARAM_0 by 1 ...
    ::
    :: In your batch file call getopt as:
    ::      call GetOpt.btm %$
    ::
    :: I also recommend setting setlocal and endlocal in the host batch file so that
    :: the option / param variable do not stick around after the host batch files exits.
    ::
    :: Example usage:  BatchFile.btm /a /b:22 /longopt Parm1 Parm2 /quotedArg:"long quoted arg"
    ::   OPTION_a will equal 1.
    ::   OPTION_b will equal 22
    ::   OPTION_quotedArg will equal "long quoted arg"
    ::   OPTION_longopt will eqal 1.
    ::   PARAM_1 will equal Parm1
    ::   PARAM_2 will equal Parm2
    ::   PARAM_0 will be set to the number of parms, so 2 in this case
    ::
    :: To get debug messages, set DEBUG=1.  This will give detailed information for each
    :: parameter on the command line as getopt loops through the list.
    ::
    :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    :: Clean up the environment before we get going
    unset getopt* OPTION_* PARAM_*
    set getopt_ParmCounter=1
    
    :: If in debug mode, kick off the display by showing the number of arguments
    if defined DEBUG echo GetOpt is processing %# arguments:
    
    :: Loop through all command line arguments one at a time.
    for /L %i in (1,1,%#) do (
       if defined DEBUG (echo. %+ echo Scan #%i:)
    
       :: If first character starts with a - or / it must be an option
       iff %@instr[0,1,%[%i]] == - .or. %@instr[0,1,%[%i]] == / then
          set getopt_Parm=%[%i]
          if defined DEBUG echo  - Item "%getopt_Parm" is an option.
    
          :: Set the Equal Index to the position of the colon.  0 means none was found
          set getopt_EqIdx=%@index[%getopt_Parm,:]
    
          :: Display the index position of the colon
          if defined DEBUG .AND. %getopt_EqIdx GE 0 echo  - Found colon at index position "%getopt_EqIdx"
    
          :: If the index is GE 0 then we must have a colon in the option.
          :: set the OPTION value to the stuff to the right of the colon
          iff %getopt_EqIdx ge 0 then
             set getopt_ParmName=%@instr[2, %@Dec[%getopt_EqIdx] , %getopt_Parm]
             if defined DEBUG echo  - ParmName  = "%getopt_ParmName"
             set getopt_ParmValue=%@right[%@eval[-%getopt_EqIdx-1],%getopt_Parm]
             if defined DEBUG echo  - Parmvalue = "%getopt_ParmValue"
             set OPTION_%getopt_ParmName=%getopt_ParmValue
          else
             :: This is a flag, so simply set the value to 1
             if defined DEBUG echo  - No colon found in "%getopt_Parm"
             set getopt_ParmName=%@right[%@Dec[%@len[%getopt_Parm]],%getopt_Parm]
             set getopt_ParmValue=1
             if defined DEBUG echo  - ParmName = "%getopt_ParmName"
             set OPTION_%getopt_ParmName=%getopt_ParmValue
          endiff
    
          :: Regardless if there was a value or not, display what is going to occur
          if defined DEBUG echo  - Setting Variable OPTION_%getopt_ParmName=%getopt_ParmValue
       else
          :: There was no / or - found, therefore this must be a paramater, not an option
          if defined DEBUG echo  - "%[%i]" is a parameter, not an option
          set PARAM_%getopt_ParmCounter=%[%i]
          set PARAM_0=%getopt_ParmCounter
          if defined DEBUG echo  - Updating Number of Parms.  PARAM_0=%PARAM_0
          if defined DEBUG echo  - Setting Variable PARAM_%getopt_ParmCounter = %[%i]
          set getopt_ParmCounter=%@Inc[%getopt_ParmCounter]
       endiff
    )
    
    :: Display additional information
    iff defined DEBUG then
       echo.
       echo There were %PARAM_0 parameters found.  Setting PARAM_0=%PARAM_0
       echo.
       echo GetOpt has completed processing %# arguments.  Ending Execution.
    endiff
    
    :: Perform cleanup
    unset getopt_*
     
  2. Steve Fabian

    Joined:
    May 20, 2008
    Messages:
    3,523
    Likes Received:
    4
    GetOpt.btm - Processing command line options & parameters in a batch file

    For reasons unknown, I the message below could not be delivered as a
    response to tc_tips@jpsoft.com:

    Steve Fabian wrote:
    | nchernoff wrote:
    || Migrated From JP Software Wiki
    ||
    || *Overview*
    |
    | PLEASE think of us whose mail client returns the "subject" in small,
    | low contrast font - it is NOT legible! It is not part of the message
    | body, either. It is NOT suitable to use as a TITLE for an ARTICLE.
    |
    | To find out the subject of the message outside of the browser, I have
    | to change screen resolution (yes, I do have a hotkey to do that), but
    | that increases text size so most lines wrap. Now I have to change
    | screensize back. Lots of wasted time.
    --
    Steve
     
  3. Fross

    Joined:
    May 30, 2008
    Messages:
    222
    Likes Received:
    1
    Hello everyone,

    I'm not sure if anyone uses this, but I've made a few tweaks to this over time and thought I would post an updated version. I'm also going to post another script I've written that calls this so I thought I would post getopt.btm first.

    I use mercurial for source code management. You can always get the latest version of GetOpt.btm at:

    or if you use Mercurial, you can clone the repository using:


    I've been using this for years and it meets my needs very well. If you have ideas or questions, please let me know. I've love to hear what folks think (good and bad).

    Thanks,
    Fross

    Code:
    @echo off
    :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    :: GetOpt - Process command line options
    :: 
    :: Michael Fross
    :: michael@fross.org
    :: http://fross.org
    ::
    :: This program scans the command line sent to it and sets various 
    :: environment variables that coorespond to the settings.
    ::
    :: In your batch file call getopt as:
    ::call GetOpt.btm %$
    ::
    ::The %$ sends the command line to the getopt function.  Use full path if needed
    ::
    :: Options:
    :: It sets an OPTION_arg variable for each arg on the command line.
    :: If a switch, the env var is set to 1.  If a value is given via the colon sign,
    :: it's set to that value.  Note, there can not be any white space around the ':'
    ::
    :: To test for a specific option, use "If defined OPTION_arg" or "If %OPTION_arg eq value" 
    :: For example: getopt.btm -v filename
    :: "If defined OPTION_v echo Verbose is set"
    :: 
    :: Parameters:
    :: Getopt also sets a parameter variable for each paramater entered: PARAM_1 to PARAM_n
    :: PARAM_0 is a special value that contains the number of PARAMs.  Useful for looping
    :: through all of them.  For example, do i = 1 to %PARAM_0 by 1 ...
    ::
    :: I also recommend setting setlocal and endlocal in the host batch file so that
    :: the option / param variable do not stick around after the host batch files exits.
    ::
    :: Example usage:  BatchFile.btm /a /b:22 /longopt Parm1 Parm2 /quotedArg:"long quoted arg"
    ::   %OPTION_a will equal 1.
    ::   %OPTION_b will equal 22
    ::   %OPTION_quotedArg will equal "long quoted arg"
    ::   %OPTION_longopt will eqal 1.
    ::   %PARAM_1 will equal Parm1
    ::   %PARAM_2 will equal Parm2
    ::   %PARAM_0 will be set to the number of parms, so 2 in this case
    ::
    :: To get debug messages, set DEBUG=1.  This will give detailed information for each
    :: item on the command line as getopt loops through the list.
    ::
    :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
     
    :: Clean up the environment before we get going
    unset getopt* OPTION_* PARAM_*
    set getopt_ParmCounter=1
     
    :: If in debug mode, kick off the display by showing the number of arguments
    iff defined DEBUG then
    echo ---GetOpt Debug Messages Follow ----------------------------------------------
    echo GetOpt is processing %# arguments:
    endiff
     
    :: Loop through all command line arguments one at a time.
    do i = 1 to %#
    if defined DEBUG (echo. %+ echo Scan #%i:)
     
    :: If first character starts with a - or / it must be an option
    iff %@instr[0,1,%[%i]] == - .or. %@instr[0,1,%[%i]] == / then
    set getopt_Parm=%[%i]
    if defined DEBUG echo  - Item "%getopt_Parm" is an option.
     
    :: Set the Colon Index to the position of the colon.  0 means none was found
    set getopt_ColonIdx=%@index[%getopt_Parm,:]
     
    :: Display the index position of the colon
    iff defined DEBUG .AND. %getopt_ColonIdx GE 0 then
    echo  - Found colon at index position: %getopt_ColonIdx
    endiff
     
    :: If the index is GE 0 then we must have a colon in the option.
    :: set the OPTION value to the stuff to the right of the colon
    iff %getopt_ColonIdx ge 0 then
    set getopt_ParmName=%@instr[2, %@Dec[%getopt_ColonIdx] , %getopt_Parm]
    if defined DEBUG echo  - ParmName  = "%getopt_ParmName"
    set getopt_ParmValue=%@right[%@eval[-%getopt_ColonIdx-1],%getopt_Parm]
    if defined DEBUG echo  - Parmvalue = "%getopt_ParmValue"
    set OPTION_%getopt_ParmName=%getopt_ParmValue
    else
    :: This is a flag, so simply set the value to 1
    if defined DEBUG echo  - No colon found in "%getopt_Parm"
    set getopt_ParmName=%@right[%@Dec[%@len[%getopt_Parm]],%getopt_Parm]
    set getopt_ParmValue=1
    if defined DEBUG echo  - ParmName = "%getopt_ParmName"
    set OPTION_%getopt_ParmName=%getopt_ParmValue
    endiff
     
    :: Regardless if there was a value or not, display what is going to occur
    if defined DEBUG echo  - Setting Variable OPTION_%getopt_ParmName=%getopt_ParmValue
    else
    :: There was no / or - found, therefore this must be a paramater, not an option
    if defined DEBUG echo  - "%[%i]" is a parameter, not an option
    set PARAM_%getopt_ParmCounter=%[%i]
    set PARAM_0=%getopt_ParmCounter
    if defined DEBUG echo  - Updating Number of Parms.  PARAM_0=%PARAM_0
    if defined DEBUG echo  - Setting Variable PARAM_%getopt_ParmCounter = %[%i]
    set getopt_ParmCounter=%@Inc[%getopt_ParmCounter]
    endiff
    enddo
     
    :: Perform cleanup
    unset getopt_* 
     
    :: Display summary information
    iff defined DEBUG then
    echo.
    echo There were %PARAM_0 parameters found.  Setting PARAM_0=%PARAM_0
    echo.
    echo GetOpt has completed processing %# arguments.  Ending Execution.
    echo ---End GetOpt Debug Messages -------------------------------------------------
    endiff
    
     
  4. epement

    Joined:
    Jun 28, 2008
    Messages:
    67
    Likes Received:
    2
    This reminds me of getopts, a 4DOS/4NT/TCC option parser which I wrote in 2001:

    Code:
    GETOPTS.BTM version 1.1 - DOCUMENTATION
     
    SUMMARY
     
      The purpose of GETOPTS.BTM is to allow 4DOS batch files to support
      Unix-style option switches on the command line. The idea is that a
      4DOS batch file can "call" GETOPTS, which locates and parses each
      option and sets environment variables, while the parent batch file
      determines which switches are allowed and handles other details. I
      wrote GETOPTS to mimic, within reason, the operation of "getopts"
      in the Unix/GNU/Linux environment.
     
      GETOPTS.BTM was written by Eric Pement ([eaddress redacted]) in
      December 2001. Your feedback and suggestions for improvement are
      welcome. It is freely offered to the 4DOS user community under the
      terms of the GNU General Public License (version 2).
     
    SYNTAX:
     
      When GETOPTS is active, the following command lines are equivalent:
     
          cmd -a -b -C -w foo -W "one two" word1 word2
          cmd -ba -wfoo -C -W"one two" -- word1 word2
          cmd word1 word2 -abCwfoo -W"one two"
          cmd -W "one two" word1 -bw foo word2 -aC
     
      Given the example above, GETOPTS will create and return the
      following environment variables to the parent batch file:
     
          OPTIONS=a b C!    - a list of character switches used
          STRINGS=LC_w UC_W  - a list of string switches used
          LC_W=foo          - each string switch has a separate variable
          UC_W="one two"    - case-sensitivity is kept by LC_ or UC_
     
      Moreover, the command tail %& will be reset to "word1 word2" since
      all the options and option-arguments have been stripped out.
     
    FEATURES SUPPORTED:
     
      * Position-independent switch clustering
          "-a -b -c" equals "-ac -b" equals "-c -ba" equals "-bac".
     
      * 3 types of switches:
          Character switches, String switches, and Numeric options.
     
      * Case-sensitive character switches
          Character switches are one character (a-z or A-Z) which never
          take an argument or parameter. They are case-sensitive, meaning
          that "-d" and "-D" are seen as different switches.
     
      * Case-sensitive string switches
          String switches are one character (a-z or A-Z) which MUST take
          an argument or parameter. Thus, -f and -F may accept different
          arguments which may be passed as '-fhello' or '-F goodbye'.
          Multi-word arguments are permitted if they are enclosed in
          double quotes, such as '-g "one or more words"'.
     
      * Numeric options
          Numeric options may be permitted or forbidden. If permitted,
          -123 will set N=123, and --456 will set N=-456.
     
      * Switches and argument removed from the command tail
          Under GETOPTS, all switches and switch parameters on the
          command line are placed into appropriate environment variables
          (see SYNTAX: for examples, above). The switches are then
          removed from the command tail (%&). If the batch file executes
          external utilities, the utility's own option syntax can be used
          (e.g., /opt1, opt2:opt3, word=opt4, etc.).
     
      * Halt on invalid options
          The parent batch file contains a list of permissible letters for
          character and string options, and tells whether numeric options
          are allowed. The GETOPTS batch file first checks the list itself
          and then checks each option on the command-tail for validity.
          GETOPTS will halt if it detects invalid options, but it can be
          set to "pass" invalid options through instead.
     
      * Switch termination
          To permit processing filenames which begin with leading
          hyphens, the switch "--" terminates switch processing, and the
          rest of the command tail is returned untouched to the parent
          batch file. Further, a single hyphen "-" by itself is passed
          without modification to the command tail.
     
    [... rest omitted ...]
    
    Klaus Meinhard was kind enough to give it an award on his web site, http://www.4dos.info , and I continue to use getopts.btm to this day, virtually unmodified.

    I will take a look at your version !!

    --
    Eric Pement
     
  5. Fross

    Joined:
    May 30, 2008
    Messages:
    222
    Likes Received:
    1
    Thanks Eric. If I would have known there was another one out there I would probably never have written it! (Although I remember I was sitting on a plane and bored...)

    If you have any ideas or suggestions please let me know. I use this little guy in almost every batch file I write.

    Also, setting DEBUG=1 before running it will give you a pretty good idea of what's going on inside. See below for an example.

    Thanks,

    Michael

    Code:
    C:\Users\Michael>set DEBUG=1
     
    C:\Users\Michael>C:\utils\GetOpt.btm /a -b /longopt /evenlonger:123 cmdline1 -q cmdline2
     
    ---GetOpt Debug Messages Follow ----------------------------------------------
    GetOpt is processing 7 arguments:
     
    Scan #1:
     - Item "/a" is an option.
     - No colon found in "/a"
     - ParmName = "a"
     - Setting Variable OPTION_a=1
     
    Scan #2:
     - Item "-b" is an option.
     - No colon found in "-b"
     - ParmName = "b"
     - Setting Variable OPTION_b=1
     
    Scan #3:
     - Item "/longopt" is an option.
     - No colon found in "/longopt"
     - ParmName = "longopt"
     - Setting Variable OPTION_longopt=1
     
    Scan #4:
     - Item "/evenlonger:123" is an option.
     - Found colon at index position: 11
     - ParmName  = "evenlonger"
     - Parmvalue = "123"
     - Setting Variable OPTION_evenlonger=123
     
    Scan #5:
     - "cmdline1" is a parameter, not an option
     - Updating Number of Parms.  PARAM_0=1
     - Setting Variable PARAM_1 = cmdline1
     
    Scan #6:
     - Item "-q" is an option.
     - No colon found in "-q"
     - ParmName = "q"
     - Setting Variable OPTION_q=1
     
    Scan #7:
     - "cmdline2" is a parameter, not an option
     - Updating Number of Parms.  PARAM_0=2
     - Setting Variable PARAM_2 = cmdline2
     
    There were 2 parameters found.  Setting PARAM_0=2
     
    GetOpt has completed processing 7 arguments.  Ending Execution.
    ---End GetOpt Debug Messages -------------------------------------------------
    
     

Share This Page