command line fun – windows flow control

Windows batch files are not nearly as rich as some languages (perl or python) and certainly not as rich as the shell scripting.

Not all of the familiar control structures exist but it is possible to create some as necessary and there are definitely enough to do write some batch files.

if / then / else

The most basic element that most developers use in their batch files is the if/then statement.  With this, you can compare strings or numbers and execute blocks of code or goto a different part of the script.

Just like C, the syntax of the if then actually drops the entire “then” from the statement.

@echo off
set a=4

if %a% equ 4 (
echo a=4
)

As the name implies, it is also possible to have an else statement added to our if clause.

@echo off
set /a a=4

if %a% equ 4 (
echo a=4
) else (
echo a is not equal 4
)

It should be obvious that left and right parenthesis are used to create the block of code to be executed.  The only thing not obvious about this statement is that the actual structure of the statement must be exactly as seen above.

“) else (“

The batch interpreter is very limited and does not allow you to add more white space, in the form of new lines, around the else statement.  This may be frustrating for someone who likes to format their code in a very specific manner but once you are aware of this short coming it is easy to work around.

There are six comparison verbs that can be used in the if/then/else tests.

EQU equal
NEQ not equal
LSS less than
LEQ less than or equal
GTR greater than
GEQ greater than or equal

small gotchas

Not every script necessarily does math, the numbers may not be important at all for what you do.  If you do not indicate that you are doing numeric calculations, then the batch interpreter thinks that you are doing string addition not numeric calculations.

set a=4
set a=%a%+1
echo a=%a%
> a=4+1

However, if you plan on doing math, you have to make sure that you add the “/a” to the set command.

set a=4
set /a a=%a%+1
echo a=%a%
> a=5

 

other verbs

The batch interpreter, just like the bash shell, has some additional support for checking that files do or do not exist.

@echo off
IF EXIST "temp.txt" (
    ECHO found
) ELSE (
    ECHO not found
)

To negate the test, simply add the key word NOT in front of exist.

@echo off
cd /d c:\temp
if NOT exist "%1" echo file %1 exists

for loop – processing files

There are a number of different types of actions that are supported with the for loop.  The for loop doesn’t seem quite as flexible as the for loop in Linux but powerful enough to gather up a list of all files in a directory to be processed.

@echo off
SET count=1
FOR /f %%G IN ('dir /b *.png') DO (call :forloopfunct"%%G")
echo here
GOTO :eof

:forloopfunct
echo %count%:%1
set /a count+=1
GOTO :eof

echo i am now here

This example will loop through all files in the current directory that have the extension of png.  The syntax for windows batch files is somewhat different than in Linux.  For loops in windows batch files do not have a block of commands associated with the for loop itself.  If you want to execute a number of commands as part of the for loop, you need to have a similar construct, where the block of commands are put into a function that is called.

This script is a complete script despite what looks to be missing labels. It appears that the eof label in the subroutine is essentially a return statement.  The same is true earlier in the script, the first “goto :eof” appears to also be a return statement.  The final echo statement in the script is never executed.

There are a number of qualifiers that you can use in a for loop.

qualifier Description
/F List of all files in current directory.
/R Recursive search through all sub-directories
/D List of directories
/L For loop over a range of numbers

for loop – over a range of numbers

It is possible to do a more standard for loop, from a starting number stepping up to a final value.

@echo off
 FOR /L %%i IN (0 2 100) DO (
 echo %%i
 echo hiya
 )

This small example starts at zero and counts up by two until equal one hundred.

The syntax is slightly different than the other for loops described.  It is also possible to call a subroutine for each element but in this type of a loop it is possible to have a block of commands to be executed with iteration.

 

pseudo case statement

There is no switch statement in windows, but it is possible to create one using a goto statement and clever use of labels to create a switch statement.

@echo off
SET I=1

GOTO LABEL_%I%
:LABEL_0
ECHO i equals 0
GOTO END_SWITCH

:LABEL_1
ECHO i equals 1
GOTO END_CASE
:END_CASE
echo program finished

 

functions

The best way to keep your code clean and easy to understand is to modularize it into functions.  Windows also supports this by allowing you to create subroutines.

It seems to be an odd to me, but Microsoft implemented this much like basic from years ago.  To call a subroutine you have to actually say “call” and the name of the subroutine.

@ECHO OFF

:: script global variables
SET day=23 
SET month=11
SET year=2015

::main
call displaydate %day% %month% %year%
goto :eoj

:displaydate
echo %year%%month%%day%
goto :eof

 

Other tricks

It is possible to run the normal dos commands and have the output assigned to a variable. Simply surround the command with percentage symbols and treat it like a variable and the output from the command will be expanded and assigned like a variable.

@echo off
set currentdirectory=%cd%
echo the current directory is %currentdirectory%

It is possible to save the current working directory in the manner described above.  This allows the script to change directories and easily find its way back to where it started.  However, there is an even nicer way to do that particular trick.

Microsoft has two commands that will save the current working directory while changing to a new directory.  This is implemented as a LIFO stack, so it is possible to always return to the last directory that you were in.

@echo off
echo starting script

echo amount of space used in temp directory
pushd c:\temp
du -h .

echo " "
echo list of users who had logged into this machine
pushd c:\users
echo now i am in %cd%
dir /b /q *.

echo " "
echo information about disk in general
if exist "c:\program files\windows media player" (
echo found it
dir "c:\program files\windows media player\wmplayer.exe"
) else (
echo cannot find windows media player
)

:: pull directories off stack
popd
echo now i am in %cd%
popd
echo now i am in %cd%

It is possible enhance your windows machine by downloading or writing comand line utilities.  One that might be interesting is the windows du, similar to the unix du but runs on windows.

windows utility du
https://technet.microsoft.com/en-us/sysinternals/du.aspx

This entry was posted in Command line, programming and tagged , . Bookmark the permalink.