Batch Files, with extension .bat, were DOS equivalent of shell scripts.
DOS version (still used by DOSBox) was extremely limited, and couldn't even add numbers. Starting with OS/2 and Windows NT, .bat files were extended with some very rudimentary scripting capabilities, so that's what we'll be doing today, but I'll limit my use of these extended features to just set /a for math.
You can run these examples on any Windows machine. Due to set /a they won't work on a DOSBox, or on a DOS machine if you somehow still have one.
Hello, World!
We can start by writing hello.bat:
echo Hello, World! Unfortunately it does a very annoying thing, and echos every command before executing it. That's fine for debugging, but not really what we want most of the time:
C:\> hello C:\> echo Hello, World! Hello, World! C:\> We can modify this by putting @ before the command, or we can just disable command echo-ing completely with @echo off.
@echo off echo Hello, World! C:\> hello2 Hello, World! C:\> I'm still not sure where that extra newline is coming from, but let's not worry about it for now.
Variables
We can set variables with set name=value, and insert them into other commands with %name%.
@echo off set name=Alice echo Hello, %name%! C:\> vars Hello, Alice! C:\> This is about the point where we could still run those examples on DOSBox or a DOS machine. From this point on, it's all Windows extensions.
Math
DOS .bat files had no way to do math, but Windows added set /a for it:
@echo off set /a a = 40 set /a b = 380 set /a c = %a% + %b% echo %c% C:\> math 420 C:\> Loop
@echo off set /a i = 1 :loop echo %i% set /a i = 1 + %i% if %i% neq 11 goto :loop C:\> loop 1 2 3 4 5 6 7 8 9 10 C:\> What's going on here:
- we set initial value of
ito 1 - we have a label
:loop - every iteration we echo current value of
i - then we increase
iby1 - if
iis not equal to11, we jump to:loop
Fibonacci
Functions are hard, so let's do iterative solution. We just do a bunch of variable assignments and additions in a loop. We don't need any new features here:
@echo off set /a i = 1 set /a a = 1 set /a b = 1 :loop echo fib(%i%)=%a% set /a i = 1 + %i% set /a c = %a% + %b% set /a a = %b% set /a b = %c% if %i% neq 21 goto :loop C:\> fib fib(1)=1 fib(2)=1 fib(3)=2 fib(4)=3 fib(5)=5 fib(6)=8 fib(7)=13 fib(8)=21 fib(9)=34 fib(10)=55 fib(11)=89 fib(12)=144 fib(13)=233 fib(14)=377 fib(15)=610 fib(16)=987 fib(17)=1597 fib(18)=2584 fib(19)=4181 fib(20)=6765 C:\> FizzBuzz
@echo off set /a i = 1 :loop set /a fizzbuzz = %i% %% 15 set /a fizz = %i% %% 3 set /a buzz = %i% %% 5 set /a t = %i% if %fizz% == 0 set t=Fizz if %buzz% == 0 set t=Buzz if %fizzbuzz% == 0 set t=FizzBuzz echo %t% set /a i = 1 + %i% if %i% neq 101 goto :loop C:\>fizzbuzz 1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz ... We can do set conditionally just like we can do goto.
FizzBuzz, modern version
So far I used just DOS features and set /a. But Windows added a lot of features to .bat files - carefully gating them behind extra sigils and switches to maintain backwards compatibility.
If we wanted to use all the features, here's what FizzBuzz would be like:
@echo off setlocal enableDelayedExpansion for /l %%j in (1 1 100) do ( set /a fizz = %%j %% 3 set /a buzz = %%j %% 5 set /a fizzbuzz = %%j %% 15 if !fizzbuzz! == 0 ( echo FizzBuzz ) else if !buzz! == 0 ( echo Buzz ) else if !fizz! == 0 ( echo Fizz ) else ( echo %%j ) ) But at this point we might just as well use PowerShell.
Should you use Windows Batch Files?
No. If you need to script a Windows machine, PowerShell is already there for you. And if it's something more complex, you might just as well use a real programming language.
Code
All code examples for the series will be in this repository.
Top comments (0)