The language has no libraries, so authors have built up patterns from the pieces on the other pages. Each example here uses only what those pages describe.
A standard header
@echo off
setlocal enableextensions enabledelayedexpansion
pushd "%~dp0"
rem ... the work ...
popd
endlocal
exit /b 0
@echo off hides the commands, setlocal keeps variables from leaking, and
pushd "%~dp0" makes the folder of the script the current folder whatever the caller’s was,
and works from a network path too.
Arguments with defaults and help
if "%~1"=="/?" goto help
if "%~1"=="" (set "target=%CD%") else (set "target=%~f1")
if not exist "%target%\" (
echo Folder not found: %target% 1>&2
exit /b 2
)
Messages to the user of the script go to handle 2 with 1>&2.
Functions with a result
call :trim " padded " result
echo [%result%]
exit /b
:trim
setlocal enabledelayedexpansion
set "s=%~1"
for /f "tokens=* delims= " %%a in ("!s!") do set "s=%%a"
:strip
if "!s:~-1!"==" " set "s=!s:~0,-1!" & goto strip
endlocal & set "%~2=%s%"
exit /b
The result crosses endlocal by being expanded on the same line (Variables). The name of the variable to fill is passed as an argument.
Menus and prompts
:menu
echo 1. Build
echo 2. Clean
choice /c 12Q /n /m "Choose: "
if errorlevel 3 exit /b 0
if errorlevel 2 goto clean
if errorlevel 1 goto build
goto menu
choice returns the position of the key chosen, and if errorlevel tests “this or higher”, so the tests run from the highest to the lowest. Without choice (DOS), set /p answer= and if /i "%answer%"=="y" do the same.
Here-text inside the script
There is no here-document. Two ways to keep a block of text in the file are a run of echo
lines in a block, and lines that start with a marker which the script reads back from itself:
(
echo [section]
echo name=%USERNAME%
echo ^<done^>
) > "%TEMP%\config.ini"
for /f "tokens=* delims=:" %%l in ('findstr /b ":::" "%~f0"') do echo %%l
goto :eof
::: Usage: tool [options]
::: Prints a message for each file.
The lines that begin ::: are labels, so they are skipped when the file is run, and
findstr finds them by that start. A <nul set /p =text prints text with no line end.
Checking for administrator rights
net session >nul 2>&1
if errorlevel 1 (
echo Run this script as administrator.
exit /b 1
)
net session succeeds only in an elevated session; it is a reported test, not a Microsoft recommendation.
Temporary files and logging
set "tmp_file=%TEMP%\job_%RANDOM%.tmp"
echo %DATE% %TIME% start >> "%~dpn0.log"
somecommand > "%tmp_file%" 2>&1 || echo failed >> "%~dpn0.log"
del "%tmp_file%" 2>nul
%~dpn0 is the script’s own path without its extension, so the log sits beside it with the same name.
Scripts that carry another program
A batch file can hold a program in another language after the part cmd.exe runs, so that
one file works as both. The batch part ends with exit or goto so that the
interpreter never reads the rest.
Perl, as pl2bat writes it. The first line is a rem that is also
the start of a Perl string, so Perl skips the batch part, and perl -x starts at the
#!perl line:
@rem = '--*-Perl-*--
@echo off
perl -x -S "%0" %*
goto endofperl
@rem ';
#!perl
print "Hello from Perl\n";
__END__
:endofperl
The viewer does not colour the Perl part: from a #! line to the next label line it reads
nothing as batch.
PowerShell is often started on the file itself with the batch part hidden in a block comment
that PowerShell ignores and cmd.exe does not mind:
powershell -nop -c "iex ((gc '%~f0') -join \"`n\")" followed by goto :eof. The
exact forms vary and none is described by Microsoft, so this page does not give a complete one.
Odd but used
(goto) 2>nul & del "%~f0"– reported: a batch file that deletes itself. Adelof the running file would otherwise be refused or break the read of the next line.echo(orecho.for a blank line;echo:%x%for a line that may be empty.for /l %%i in (1,1,1000000) do rem– a crude pause;timeout /t 5 /nobreak >nulis the proper form.cmd /c exit 3– setsERRORLEVELto 3 without leaving the batch file.%~dp0with a trailing backslash: write%~dp0file.txt, not%~dp0\file.txt, which works but doubles the slash.
Not described
Unknown
- Reference: these patterns are collected from common practice and the commands’ Microsoft pages; the examples were not run on Windows for this page, so a corner case may differ.