Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / operating-systems / DOS

Batchography: 8 Batch File Tricks for Daily Use

4.69/5 (4 votes)
9 Apr 2019CPOL5 min read 30.7K  
Practical and useful Batch files scripts for beginners and advanced users

Introduction

Back in 2016, I decided to learn as much as I can about the Batch files programming language because Batch was my first programming language when I was a kid. Today I share with you some of those Batchography tips.

Background

If you have done some basic command prompt work (cmd.exe) and/or have written basic Batch files, then please skip this section.

If you have never done Batch files programming, then welcome. Just run "cmd.exe" to open the command prompt, then type: "notepad hello.bat".

In Notepad, just type the following:

@echo off

echo Welcome to the Batch Programming World!

Close Notepad and save the file. Now back to the command prompt, type: "hello.bat" and hit the ENTER key.

That's it! That was your first Batch file script which outputs the message from above.

It is advisable that you know some programming concepts to proceed with the remainder of this article.

Trick #1 - Taking user input and doing arithmetic operations

Often times, it is very important to write interactive scripts that take input from the user and carry arithmetic operations if needed.

To read user input, we can use the following syntax:

SET /P VarName=The prompt text

So for example, to ask the user for his/her name and display it back again, we can do the following:

@echo off

setlocal

SET /P Name="What is your name? "
echo Welcome %Name%
Quote:

It is important not to pollute the environment variables namespace when using the "SET" command and therefore it is a good practice to start your script with the "setlocal" command that will revert the environment variable changes when the script terminates.

Similarily, to do arithmetic operations, we can use the following syntax:

SET /A Number=Expression

For example:

SET /A Number=1+2+3+4

Would compute into the variable "Number" the value "10".

Now, we can combine those two tricks to create a small integer expression calculator:

@echo off

setlocal

:repeat
    SET /P Expr="Please enter an expression (or 'q') to quit:"
    SET /A Result=%Expr%
    if "%Expr%"==""  goto :eof
    if "%Expr%"=="q" goto :eof
    echo The result is %Result%
    goto repeat

Here's a sample output from this script:

C:\Temp\Batchography>expr-calc.bat
Please enter an expression (or 'q') to quit:1+2+3
The result is 6
Please enter an expression (or 'q') to quit:-5+2
The result is -3
Please enter an expression (or 'q') to quit:q

C:\Temp\Batchography>

Trick #2 - Number counting

Number counting can come in handy in many scenarios. It could be used to create numbered dummy folders, write an algorithm that requires counting, or anything else you can think of.

In Batch files, to count, you can use the following syntax:

FOR /L %variable IN (start, step, end) DO command [command-parameters]

Let's illustrate by writing a small script that creates 10 dummy folders: "folder1" to "folder10":

So let's assume we have the following files:

@echo off
for /L %%a in (1, 1, 10) do (
    mkdir folder%%a
)

For example, let us write the sigma function (do the addition from 1 to N):

@echo off

setlocal

:repeat
    SET /P N="Please N for the sigma computation:"
    SET /A Result=0
    for /L %%i in (1, 1, %N%) do (
        SET /A Result=Result+%%i
    )
    echo Sigma(%N%)=%Result%

Trick #3 - Reading a text file line by line in Batch files

Reading from a text file, one line at a time can be very handy for text scanning and transformation. Use the "FOR /F" syntax like this:

@echo off
for /f "delims=" %%a in (the-file.txt) DO ( 
  ECHO Line is: %%a
)

We can implement a very basic non-empty lines counter in text files using the Batch language like this:

@echo off

setlocal enabledelayedexpansion

if "%1"=="" (
    echo Please specify a file name!
    goto :eof
)

set /A nlines=0
for /f "delims=" %%a in (%1) DO ( 
  set /A nlines+=1
)

echo Total non-empty lines: %nlines%
Quote:

The "FOR /F" will skip empty lines in input text files.

Trick #4 - String substitution

With the Batch scripting language, it is possible to do string substitution. To achieve that, we have to have the string in question inside an environment variable. We can then use the following syntax:

%VarName:StringToBeMatched=StringToBeReplacedWith%

Let's write an interactive script that replaces the word "books" with "ebooks" in the file "email.txt":

Reading books was the norm during his grandfather's time.
People used to carry books with them to school in order to read and study.
Some say that books will become obsolete one day. Who knows.

The following script will do the string substitution and generate a new file called "new-email.txt":

@echo off

setlocal enabledelayedexpansion

if exist new-email.txt del new-email.txt

for /f "delims=" %%a in (email.txt) DO ( 
  set line=%%a
  echo !line:books=ebooks! >>new-email.txt
)
Quote:

We use the "setlocal enabledelayedexpansion" and the "!Var!" syntax instead of "%Var%" syntax when we are expanding variables from inside compound statements.

The "new-email.txt" contents are:

Reading ebooks was the norm during his grandfather's time. 
People used to carry ebooks with them to school in order to read and study. 
Some say that ebooks will become obsolete one day. Who knows. 

 

Trick #5 - Polyglot scripts: Mixing Python and Batch files

A very fun trick is when we can have a script that runs successfully under two or more languages. Let's illustrate how to do a mixed script for running Python and Batch files:

@echo off
rem = """
:: From here and on, write any Batch file syntax and it will be ignored by Python

:: 
:: The Batchography book by Elias Bachaalany
::

python -x "%~f0" %*
exit /b %errorlevel%
:: End of batch file commands
"""

# Anything here is interpreted by Python

import platform
import sys

print("Hello world from Python %s!\n" % platform.python_version())
print("The passed arguments are: %s" % sys.argv[1:])

The above is a Batch script that invokes itself again as a Python script using the "python -x" switch (skip the first line).

Such scripts is useful when you first want a Batch script to set up or verify the right environment before invoking its embedded Python code.

Trick #6 - Polyglot scripts: A self-compiling C++ and Batch file

Similar to Trick #5, we can make a Batch file script that is also a C++ program. Here's how we can make a self-compiling C++ Batch script:

/* 2>nul && echo | set /p=
@echo off
setlocal
echo.                                                                                                     
::
:: Self-compiling C++ Batch file!
::
:: (c) Batchography book - by Elias Bachaalany
::

set outfile="%~dpn0.exe"

cl %~dpf0 /TP /EHsc /link /out:%outfile% /nologo > nul

if exist %outfile% (
    %outfile%
    del %outfile%
    del "%~dpn0.obj"
) else (
  echo Compilation failed!
)
goto :eof
*/

#include <stdio.h>

int main()
{
    printf(
    	"Hello world! I was self-compiled!\n"
        "\n"
        "Checkout the Batchography book!\n");
    
    return 0;
}

There's a slight drawback in this polyglot script. The first line ("/*" a C multi-line comment opening) is not a valid command and it will cause an error but we redirect the error to the nul device. We close the multi-line comment (with "*/") shortly after exiting the Batch file.

Trick #7 - Tokenizing commands output

It is possible to execute a command then break its output into tokens. To achieve this, we will use the "FOR /F" syntax.

From the command prompt, to query the registry and retrieve the language ID, we can use the "reg.exe" command like such:

C:\Temp\Batchography>reg query "hklm\system\controlset001\control\nls\language" /v Installlanguage


HKEY_LOCAL_MACHINE\system\controlset001\control\nls\language
    Installlanguage    REG_SZ    0409

C:\Temp\Batchography>

We have two lines output. We only care about the second line and the 3rd token (if we tokenize the string using the space character). To retrieve the 0409 value and write a Batch script to detect the system language, we can do the following:

@echo off

for /F "usebackq tokens=3" %%a IN (`reg query "hklm\system\controlset001\control\nls\language" /v Installlanguage`) DO (
  set lang_id=%%a
)

:: 0409 English ; 0407 German ; 040C French ; 0C0A Spanish

if "%lang_id%"=="0409" (
      echo English detected
) else if "%lang_id%" == "040C" (
      echo French detected
) else (
      echo Note: Unknown language ID %lang_id%!
)

The Batch script above, filters for lines that have at least 3 tokens and it captures the first token only.

Trick #8 - Functions are fun

Who said the Batch language is a simple language? Did you know that you can write functions (even recursive ones)?

To define a function, simply create a label and then call it:

@echo off

setlocal

:main
    echo Hello!
    set /p a=Enter the   first number:
    set /p b=Enter thne second number:

    call :add result %a% %b%
    echo The result is: %result%
    goto :eof

:add <1=return var> <2=first number> <3=second number>
    echo Adding '%2' and '%3'. Returning the result into the variable '%1'
    set /a %1=%2+%3
    goto :eof

The function "add", is just a label and what comes after it in the same line are ignored / free text. As a convention, we put the argument number and its description. The "add" function is defined to take a return variable name (argument #1) and two numbers "a" (argument #2) and "b" (argument #3).

The "main" function calls "add" using the "call :func_name" syntax and passing the arguments thereafter. When "add" returns, it may call "goto :eof" or "exit /b <return_code>".

Conclusion

The Batch programming is an old but a beautiful language. It has so many features that I was delighted to research and learn about.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)