Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!

GetOpt - Process Command Line Options

May
446
4
Many years ago I created a GetOpt batch file so that I could process command line arguments effectively. I've posted this before, but you can read much more about how this works at the following link:


I use this extensively in my batch files and library functions. I have since updated this to work as a library function and the code is below. If you'd rather just use it as a batch file, remove the first and last line. If anyone has ideas or thoughts, please let me know. There is a full readme on how to use this at the above link. It's easy, but you have to know how it works.

Code:
getopt {
@echo off
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: GetOpt - Process command line options                                       Michael Fross
::                                                                         [email protected]
::                                                                  http://github.com/frossm
:: Please see the README.txt / README.md for usage information
:: Latest version located at: https://github.com/frossm/getopt.btm
::
:: LICENSE:
:: This program is licensed under the OpenSource MIT license. 
:: https://opensource.org/licenses/MIT
:: Please see the LICENSE.txt file, included with this distribution, for details
:: on acceptable use.
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:: -----------------------------------------------------------------------------------------
:: Configuration Directives
:: -----------------------------------------------------------------------------------------
:: Set UseColorOutput to 0 it disable color output while in debug mode
set UseColorOutput=1

:: Set the debug color.  Options are RED, CYAN, YELLOW, MAGENTA, WHITE, GREEN, BLACK, BLUE
set DebugColor=RED
set DebugHeaderFooterColor=WHITE


:: -----------------------------------------------------------------------------------------
:: Start of script execution
:: -----------------------------------------------------------------------------------------
:: Clean up and prep the environment before we get going
unset getopt* OPTION_* PARAM_*
set getopt_ParmCounter=1
set getopt_TotalArgs=%@Words[" ",%*]

:: If in debug mode, kick off the display by showing the number of arguments
iff defined DEBUG then
    gosub SetColor %DebugHeaderFooterColor
    echo.
    echo --- GetOpt Debug Mode Activated ------------------------------------------------

    :: Set the color of the debug output
    gosub SetColor %DebugColor

    echo.
    echo Working with command line:
    echo   %*
    echo.
    echo GetOpt is processing %getopt_TotalArgs arguments:
endiff

:: Loop through all command line arguments one at a time.
do i = 1 to %getopt_TotalArgs
    :: Empty the index variables
    unset getopt_ColonIdx getopt_EqualIdx getopt_ValueIdx

    :: Set getopt_Current to the current argument text we are working with
    set getopt_Current=%@Word[%@Dec[%i],%*]

    if defined DEBUG (echo. %+ echo Scan #%i: %getopt_Current)

    :: If first character starts with a - or / it must be an option
    iff %@instr[0,1,%getopt_Current] == - .or. %@instr[0,1,%getopt_Current] == / then
        set getopt_Parm=%getopt_Current
        if defined DEBUG echo  - Item is a switch or option

        :: Set the Colon Index to the position of the colon.  0 means none was found
        set getopt_ColonIdx=%@index[%getopt_Parm,:]

        :: Set the Equal Index to the position of the equalsign.  0 means none was found
        set getopt_EqualIdx=%@index[%getopt_Parm,=]

        :: Set the value index to the position of the colon or equal sign
        :: [Michael Giberti] If `=` and `:` are found, set the value index correctly. Ex: "/path=C:\Temp"
        iff %getopt_ColonIdx ge 0 .and. %getopt_EqualIdx ge 0 then
            set getopt_ValueIdx=%@MIN[%getopt_ColonIdx,%getopt_EqualIdx]
            iff defined DEBUG then
                 if %getopt_ValueIdx == %getopt_ColonIdx echo  - Found colon at index position: %getopt_ColonIdx
                 if %getopt_ValueIdx == %getopt_EqualIdx echo  - Found equal sign at index position: %getopt_EqualIdx
            endiff
        elseiff %getopt_ColonIdx ge 0 then
            if defined DEBUG echo  - Found colon at index position: %getopt_ColonIdx
            set getopt_ValueIdx=%getopt_ColonIdx
        elseiff %getopt_EqualIdx ge 0 then
            if defined DEBUG echo  - Found equal sign at index position: %getopt_EqualIdx
            set getopt_ValueIdx=%getopt_EqualIdx
        endiff
       
        :: If the value index is GE 0 then we must have a colon or equal sign in the option.
        :: set the OPTION value to the stuff to the right of the colon or equal sign
        iff %getopt_ValueIdx ge 0 then
            set getopt_ParmName=%@instr[2, %@Dec[%getopt_ValueIdx] , %getopt_Parm]
            if defined DEBUG echo  - ParmName  = "%getopt_ParmName"
            set getopt_ParmValue=%@right[%@eval[-%getopt_ValueIdx-1],%getopt_Parm]
            if defined DEBUG echo  - Parmvalue = "%getopt_ParmValue"
            set OPTION_%getopt_ParmName=%getopt_ParmValue
        else
            :: This is a switch, so simply set the value to 1
            if defined DEBUG echo  - No colon or equal sign 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 parameter, not an option
        if defined DEBUG echo  - "%getopt_Current" is a parameter, not a switch or option
        set PARAM_%getopt_ParmCounter=%getopt_Current
        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="%getopt_Current"
        set getopt_ParmCounter=%@Inc[%getopt_ParmCounter]
    endiff
enddo


:: Display summary information
iff defined DEBUG then
    echo.
    iff defined PARAM_0 then
        echo There were %PARAM_0 parameters found.  Setting PARAM_0=%PARAM_0
    else
        echo There were no parameters found.  PARAM_0 has not been set.
    endiff
    echo.
    echo GetOpt has completed processing %getopt_TotalArgs arguments.  Ending Execution.

    gosub SetColor %DebugHeaderFooterColor
    echo.
    echo --- End GetOpt Debug Messages -------------------------------------------------
    echo.

    :: Reset the color back to normal
    gosub SetColor Normal

endiff


:: Perform cleanup and return to the calling program
unset getopt_* UseColorOutput DebugColor DebugHeaderFooterColor

:: If Debug is set, then pause before passing control back to the calling program
::if defined DEBUG pause Press Any Key To Continue To The Calling Program...
quit


:: -----------------------------------------------------------------------------------------
:: SetColor [Color]
:: Simple routinethat sets the current console color to what is chosen.  Sending
:: the color "Normal" will set the color back to the default.
:: -----------------------------------------------------------------------------------------
:SetColor [Color]
    iff %UseColorOutput gt 0 then
        Switch %@Upper[%Color]
            Case CYAN
                echos ^e[36;1m

            Case RED
                echos ^e[31;1m

            Case YELLOW
                echos ^e[33;1m

            Case MAGENTA
                echos ^e[35;1m

            Case WHITE
                echos ^e[37;1m

            Case GREEN
                echos ^e[32;1m

            Case BLACK
                echos ^e[30m

            Case BLUE
                echos ^e[34m
       
            Case NORMAL
                echos ^e[0m

            Default
                echo ** ERROR Setting Color.  Unknown Directive:  '%Color' **
        EndSwitch
    endiff
return

}
 
Last edited:
Hi Michael @Fross - I came across the GetOpt library a while back and have been successfully using it for a while now. I've slowly been converting my scripts to use it.

First of all, thank you very much for writing and sharing this useful functionality!

I recently came across an issue when trying to pass a filename with a path as an option. (e.g. RunScript.btm /input=C:\Folder\Filename.txt).

It seems when an option contains an equal sign after the option name and the option value contains a colon, then the GetOpt logic doesn't handle it properly. If you run a test using the above argument with Debug mode on you'll see that GetOpt replaces C: with C=

I adjusted the GetOpt library changing this code:

Code:
        :: Set the value index to the position of the colon or equal sign
        iff %getopt_ColonIdx ge 0 then
            if defined DEBUG echo  - Found colon at index position: %getopt_ColonIdx
            set getopt_ValueIdx=%getopt_ColonIdx
        elseiff %getopt_EqualIdx ge 0 then
            if defined DEBUG echo  - Found equal sign at index position: %getopt_EqualIdx
            set getopt_ValueIdx=%getopt_EqualIdx
        endiff

to this:

Code:
        :: Set the value index to the position of the colon or equal sign
        iff %getopt_ColonIdx ge 0 .and. %getopt_EqualIdx ge 0 then
            set getopt_ValueIdx=%@MIN[%getopt_ColonIdx,%getopt_EqualIdx]
            iff defined DEBUG then
                 if %getopt_ValueIdx == %getopt_ColonIdx echo  - Found colon at index position: %getopt_ColonIdx
                 if %getopt_ValueIdx == %getopt_EqualIdx echo  - Found equal sign at index position: %getopt_EqualIdx
            endiff
        elseiff %getopt_ColonIdx ge 0 then
            if defined DEBUG echo  - Found colon at index position: %getopt_ColonIdx
            set getopt_ValueIdx=%getopt_ColonIdx
        elseiff %getopt_EqualIdx ge 0 then
            if defined DEBUG echo  - Found equal sign at index position: %getopt_EqualIdx
            set getopt_ValueIdx=%getopt_EqualIdx
        endiff

I added an additional IFF section at the top of this portion of the code to handle the situation where both an equal sign and colon are present. This change will use the first one found on the line as the marker of the end of the Option name.

Thought I'd share this change back here in case anyone else might find it useful.
 
Hello Michael. Thank you for the kind words and I'm surprised that I've not come across that issue after all of these years. Your updates work great during my testing.

I'm updated GitHub and I'll update the code at the top of this post.

Much appreciated. Thanks.

Michael
 
Back
Top