1

I want to do some actions in a DOS batch file depending on the incoming command line parameters.
The batch shall be invoked with any number of parameters. Possible parameters shall be (in best case extendable):

UPDATE [-verbose [outputFileName]] [-validate] [/?]

Furthermore it should be possible to enter the params in any order. Especially the param -verbose is of interest: If this parameter is given the following 'parameterParam' MUST be the name of the outputfilename or can be empty. Notice that the parameters have a leading "-". A parameter of a parameter argument has no leading "-".
For example:

UPDATE -verbose -validate

shall display execution steps on STDOUT (-verbose) and validate the input.

UPDATE -verbose outputFileName.txt -validate

shall log execution steps into a file named <outputFilename.txt> (-verbose outputFileName.txt) and validate the input.

UPDATE -validate

shall only validate the input.

UPDATE -validate -verbose

shall do the same as

UPDATE -verbose -validate

.

UPDATE /?

shall display how to use update.bat

How can I do that? Iterating over the command line arguments with a FOR loop? But how? I am able to iterate over the arguments but if -verbose is found how can I preview the following parameter to check if a filename is supplied?

According to the supplied parameter a specific action should take place (starting a different batch...) I want to invoke LiquiBase via java:

For validation:

java -jar %LIQUIBASE_EXEC% --changeLogFile=../changesets/changelog-update.xml --logLevel=info validate
java -jar %LIQUIBASE_EXEC% --changeLogFile=../changesets/changelog-views-and-sp.xml --logLevel=info validate

For offline SQL generation:

java -jar %LIQUIBASE_EXEC% --changeLogFile=../changesets/changelog-update.xml --logLevel=info updateSQL > update_%_outputfilename%
java -jar %LIQUIBASE_EXEC% --changeLogFile=../changesets/changelog-views-and-sp.xml --logLevel=info updateSQL  > viewsAndSP_%_outputfilename%
6
  • 2
    Are you really using DOS? Or cmd.exe ? Commented Sep 26, 2014 at 13:13
  • I have a file named update.bat and I want to let it run on a Windows machine in the command line tool. Commented Sep 26, 2014 at 13:20
  • Then that would be cmd.exe, I'll change the tags. Commented Sep 26, 2014 at 13:26
  • 1
    This is not a good design, because a filename can begin with -. You should add an additional -output option with a required filename argument: UPDATE [-verbose] [-validate] [-output outFile] Commented Sep 26, 2014 at 14:07
  • 1
    Have a look at stackoverflow.com/a/8162578/1012053. It does most of what you want, except you would need the -output outFile option from my prior comment, and the help option would be -? instead of /?. Commented Sep 26, 2014 at 14:10

2 Answers 2

1
@echo off

setlocal enableDelayedExpansion
set "_verbose=no"
set "_validate=no"
set "_outputfilename="
rem set "arg_counter=0"
set "_check_next=no"

if "%~1" equ "/?" call :help

for %%a in (%*) do (


    if "!_check_next!" equ "yes" (
        set "_check_next=no"
        set "arg=%%~a"

        if "!arg:~0,1!" neq "-" (
            set "_outputfilename=%%~a"
        ) else (
           if "%%~a" equ "-validate" (
               set "_validate=yes"
            )
        )
    )

    rem if "%%~a" equ "/?" call :help

    if "%%~a" equ "-verbose" (
        set "_check_next=yes"
        set "_verbose=yes"
    )

    if "%%~a" equ "-validate" (
        set "_validate=yes"
    )

)

echo --%_validate%--%_verbose%--%_outputfilename%--

endlocal
exit /b 0

:help

    echo %~0 [-verbose [outputFileName]] [-validate] [/?]
    echo some explanations

exit /b 0

the order of the arguments is not mandatory as requested.Not sure how extensible is , but arg checking code is always a verbose even on 'serious' programming languages.

Sign up to request clarification or add additional context in comments.

3 Comments

This way I get messages about ECHO... ECHO [ON | OFF]. How can I prevent from this? Your solution fills some variables. How can I use them? I want to invoke respective programs dpending on the parameters. Can I call a label like :prog1 from within the loop and after execution the loops gets continued? Or do I have to put some IFs after the loop checking the variables values and start the programs? It doesn't work for me.
@du-it there's no way for me to know what programs you want to call depending on parameters as this information is not provided.And yes it will be best to check variables and call the program you want. Betrer give more information because your question's range concerns only agruments parsing
Please see my extended question. Running the java command without any commandline commands around it works.
1

I finally get it. Here's my solution based on npocmaka's useful code:

call _set-env.bat

@echo off

setlocal enableDelayedExpansion
set argC=0
for %%x in (%*) do Set /A argC+=1

set "_verbose=no"
set "_validate=no"
set "_outputfilename="
set "_check_next=no"
set "_sandbox=no"

if "%~1" equ "/?" goto :help

if %argC% == 1 (
    if "%~1" equ "-sandbox" (
        echo.
        echo Running UPDATE with just -sandbox option does not do anything.
        echo Run UPDATE /? for usage.
        :: call :help
        goto :eof
    )
)

for %%a in (%*) do (

    if "!_check_next!" equ "yes" (
        set "_check_next=no"
        set "arg=%%~a"

        if "!arg:~0,1!" neq "-" (
            set "_outputfilename=%%~a"
        ) else (
           if "%%~a" equ "-validate" (
               set "_validate=yes"
            )
        )
    )

    if "%%~a" equ "-verbose" (
        set "_check_next=yes"
        set "_verbose=yes"
    )

    if "%%~a" equ "-validate" (
        set "_validate=yes"
    )

    if "%%~a" equ "-sandbox" (
        set "_sandbox=yes"
    )
)

if %_validate% equ yes (
    call :validateUpdate
    echo !errorlevel!
    if !errorlevel! neq 0 exit /b !errorlevel!
)
if "yes" equ "%_verbose%" (
    if "%_outputfilename%" neq "" (
        call :verboseUpdateToFile
    ) else (
        call :verboseUpdate
    )
    if !errorlevel! neq 0 exit /b !errorlevel!
)
if "no" equ "%_sandbox%" (
    call :update
)

:: echo --%_validate%--%_verbose%--%_outputfilename%--
exit /b 0

:help
    ::echo %~0 [-verbose [outputFileName]] [-validate] [/?]
    @echo Executes LiquiBase changesets to take effect on the database.
    @echo.
    @echo UPDATE [-verbose [outputFileName]] [-validate] [/?]
    @echo.  /?              Shows this help.
    @echo   -validate       Validates the changesets without executing them.
    @echo   -verbose        Prints output of the generated SQL without executing them
    @echo.
    goto :eof

:validateUpdate
    java -jar %LIQUIBASE_EXEC% --changeLogFile=../changesets/changelog-update.xml --logLevel=info validate
    :: java -jar %LIQUIBASE_EXEC% --changeLogFile=../changesets/changelog-views-and-sp.xml --logLevel=info validate
    goto :eof

:verboseUpdate
    java -jar %LIQUIBASE_EXEC% --changeLogFile=../changesets/changelog-update.xml --logLevel=info updateSQL
    java -jar %LIQUIBASE_EXEC% --changeLogFile=../changesets/changelog-views-and-sp.xml --logLevel=info updateSQL
    goto :eof

:verboseUpdateToFile
    java -jar %LIQUIBASE_EXEC% --changeLogFile=../changesets/changelog-update.xml --logLevel=info updateSQL > update_"%_outputfilename%"
    java -jar %LIQUIBASE_EXEC% --changeLogFile=../changesets/changelog-views-and-sp.xml --logLevel=info updateSQL  > viewsAndSP_"%_outputfilename%"
    goto :eof

:update
@echo update...
rem java -jar %LIQUIBASE_EXEC% --changeLogFile=../changesets/changelog-update.xml --logLevel=info update
rem java -jar %LIQUIBASE_EXEC% --changeLogFile=../changesets/changelog-views-and-sp.xml --logLevel=info update

endlocal
exit /b 0

One thing is still unclear: Let's say :validateUpdate is executed and a validation error occurs, LiquiBase prints out "Liquibase 'validate' successful" and the ERRORLEVEL is 0. Is this because LiquiBase prints out that a validation error occured but exits itself with 0 and hence ERRORLEVEL is 0? This would mean that I can't handle such validation errors anyway. I intended to run the code at label :update only if no errors occur.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.