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%
du-it
  • 2,561
  • 8
  • 42
  • 80
  • 2
    Are you _really_ using DOS? Or `cmd.exe` ? – paxdiablo Sep 26 '14 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. – du-it Sep 26 '14 at 13:20
  • Then that would be `cmd.exe`, I'll change the tags. – paxdiablo Sep 26 '14 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]` – dbenham Sep 26 '14 at 14:07
  • 1
    Have a look at http://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 `/?`. – dbenham Sep 26 '14 at 14:10
  • so when there is no `validate` parameter you want the second section of commands.When there is you want the first one? – npocmaka Sep 26 '14 at 18:18

2 Answers2

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.

npocmaka
  • 55,367
  • 18
  • 148
  • 187
  • 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 Sep 26 '14 at 17:29
  • @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 – npocmaka Sep 26 '14 at 17:43
  • Please see my extended question. Running the java command without any commandline commands around it works. – du-it Sep 26 '14 at 18:10
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.

du-it
  • 2,561
  • 8
  • 42
  • 80