100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Batch

Environment Variables in Batch

Understand how Windows Batch scripts create, read, scope, and persist environment variables, including the tricky topic of delayed expansion.

Advanced Batch ScriptingBeginner8 min readJul 10, 2026
Analogies

What Environment Variables Are in Batch

Environment variables in batch are named key-value pairs stored in the process environment block that cmd.exe inherits from its parent process and can read, modify, or export to child processes. You reference a variable's value by wrapping its name in percent signs, like %PATH% or %USERNAME%, and the shell substitutes the text before the line even executes. Because substitution happens at parse time rather than at run time by default, updating a variable mid-block of parenthesized commands behaves differently than most programmers expect, which is the root cause of many batch scripting bugs.

🏏

Cricket analogy: It is like a scoreboard operator updating the run total between overs rather than ball-by-ball — if you read the board mid-over expecting a live number, you'll see the value from when the over started, not the current ball.

Setting and Reading Variables with SET

The SET command creates or updates a variable: SET name=value with no spaces around the equals sign, since anything after the equals sign, including trailing spaces, becomes part of the value. SET /A performs integer arithmetic, so SET /A total=5+3 stores 8 rather than the literal string '5+3', while SET /P prompts the user for input and stores their typed response, useful for interactive scripts. Running SET alone with no arguments lists every currently defined environment variable, which is a handy debugging tool when a script behaves unexpectedly.

🏏

Cricket analogy: SET /A is like a scorer's calculator tallying extras plus runs off the bat into one total, while SET /P is like an umpire asking the third umpire for a live decision and recording whatever answer comes back.

batch
@echo off
SET name=John
SET /A total=5+3
SET /P city=Enter your city:
echo Hello %name%, your total is %total% and you live in %city%.

System, User, and Process-Level Scope

Windows actually maintains environment variables at three levels: system-wide (set via System Properties, applying to every user), per-user (stored in the registry under HKCU), and process-level (created at runtime, like inside your batch script). A batch script's SET command only ever modifies the process-level copy inherited by that cmd.exe instance and any children it spawns; it never writes back to the registry, so changes vanish the moment the script or its parent shell closes. To persist a variable permanently, you must use SETX instead of SET, though SETX writes to the registry and the new value is not visible in the current session until a new cmd.exe window is opened.

🏏

Cricket analogy: It is like a temporary net bowler brought in for one practice session versus a contracted squad member listed on the official team sheet for the whole series — SET is the net bowler, SETX is the registered player.

SETX has a 1024-character limit per value and, unlike SET, does not affect the currently running cmd.exe session — you must open a new terminal window to see the persisted value take effect.

Delayed Expansion for Loops and Conditionals

By default, cmd.exe expands all %variable% references once when a whole block (anything inside parentheses, such as a FOR loop or an IF/ELSE) is parsed, not each time a line inside it executes, so a variable updated inside the loop still shows its pre-loop value when read later in that same loop. Running SETLOCAL EnableDelayedExpansion at the top of the script switches to on-demand expansion using exclamation marks instead of percent signs, so !counter! reflects the value at the exact moment that line runs rather than when the block was parsed. This distinction trips up nearly every batch beginner who tries to build a running total or string inside a FOR loop and gets stuck with an unchanging value.

🏏

Cricket analogy: It is like the difference between reading a printed scorecard handed out before the innings started versus checking the live electronic scoreboard ball-by-ball — delayed expansion is the live board, normal expansion is the stale printout.

If you use ! in a string without EnableDelayedExpansion active, it's usually harmless, but if EnableDelayedExpansion IS active and your data itself legitimately contains a literal exclamation mark, that character can be silently stripped or misinterpreted — escape it as ^^! when needed.

  • Environment variables are read with %name% and set with SET name=value (no spaces around =).
  • SET /A does integer arithmetic; SET /P reads user input into a variable.
  • Batch's SET only affects the current process-level environment; it never persists across sessions.
  • SETX writes a permanent value to the registry but does not affect the currently open cmd.exe window.
  • Percent-sign expansion happens once when a block is parsed, causing stale values inside loops and IF blocks.
  • SETLOCAL EnableDelayedExpansion plus !variable! syntax gives real-time expansion inside loops.
  • Running plain SET with no arguments lists all currently defined variables, useful for debugging.

Practice what you learned

Was this page helpful?

Topics covered

#Batch#WindowsBatchScriptingStudyNotes#MicrosoftTechnologies#EnvironmentVariablesInBatch#Environment#Variables#Setting#Reading#StudyNotes#SkillVeris