In this article I will give some extra information on the usage of CMD.EXE variables in batch files.
These variables are stored in the so-called Environment, hence the name Environment Variables. There are two environments on a Windows machine: The System and the User environment.
When a variable is set in a batch file, it is set in the User environment only, and available only to that CMD.EXE process. When a new process is called from that script, the environment is copied and the copy is passed to that process.
Changes to the System environment are permanent, they survive reboots and are available to all processes and all users on the system.
Both the System as the User environment can be manipulated using the command SETX.EXE. From Windows 7, this executable is included in Windows.
The environment has a memory limit of 64KB, but as it contains only text, this limit is hard to exceed.
Naming Conventions in this article
The following abbreviations are used in this article to refer to the different types of variables available in the CMD language. Each variable type will be discussed below, and what you can and can not do with them.
- PVAR: Parameter VARiable (Examples: %0, %1)
- SVAR: Single-letter VARiable (Example: %%A)
- MVAR: Multiple-letter VARiable (Example: %COUNT%)
- AVAR: Any VARiable, this abbreviation is used when the text can be applied to any of the previous three types.
By default, in the examples I use the variable syntax as used in the CMD language in batch files. When executed from an interactive command line, the prefix for SVAR variables is a single percent sign, not a double!
So this works in an interactive command window
for %I in (a b c) do echo %I
And this is the same when stored in a batch file:
for %%I in (a b c) do echo %%I
Keep this in mind if you paste the examples below in an interactive command window!
Generic information on variable types
There are three distinct types of environment variables. All variables are recognizable because they are pre-fixed with a single or double percent sign (%) and in the case of the MVAR, also post-fixed with a percent sign. The rules for pre- and post-fixing seem difficult, but once understood, they are fairly straightforward.
Parameter variables (PVAR)
These variables consist of a single number. When referring to a PVAR, you need to prefix it with a single percent sign.
Examples: %0, %1, %9
PVARs can not be defined using the SET command. PVARs are defined from the call to the batch file *or* the subroutine. The number represents the position of the PVAR on the command line. If you address a PVAR with a number higher than the number of parameters given on the command line, the PVAR will be returned as an empty value. %0 is a special case, this refers initially to the batch file’s own full file name. To access more than 9 parameters, you can use the SHIFT command to shift out the first-most parameter (normally, %0). In Windows 2000/XP, the SHIFT command also supports a parameter to start shifting from the Nth parameter, thus allowing you to keep one or more of the lower ones. More details can be obtained using the shift /? command.
Single-letter named variables (SVAR)
These variables have a name consisting of a single letter. When referring to an SVAR, you need to prefix it with a double percent sign (in a batch file!).
Note: While you can define an SVAR using the SET command, it will be interpreted as an MVAR, and it will not have the special properties that SVARs and PVARs have.
Observe this example:
set A=This is a text rem the folllowing statement will not work echo %%A rem the following will work echo %A%
SVARs are case sensitive, so you have 52 variables of these.
SVARs are most useful when used with the FOR command, where they are mandatory.
for %%A in (A B C) do echo %%A for %%A in ("This is a text") do set WITH_QUOTES=%%A for %%A in ("This is a text") do set NO_QUOTES=%%~A
See below for an explanation on the %%~A syntax.
Multiple-letter named variables (MVAR)
MVARs have names starting with a letter, and followed by one or more letters and numbers. When referring to an MVAR, you need to prefix and post fix it with a single percent sign. When defining an MVAR using the SET command, you omit the percent signs.
set TEXT=This is a text echo %TEXT% echo %WORKFOLDER%
Setting and retrieving the value for environment variables
To use a value of environment variables, you insert its name or number into a command using the right prefix and postfix rules.
echo The name of this batchfile is: %0 echo This program is running on machine: %COMPUTERNAME% for %%A in (Text) do echo %%A SET TEXT=Hello, world! echo %TEXT%
What can you do with these variable types?
PVAR, SVAR specific: File name manipulation
With PVARs and SVARs, when the variable contains a file name, you can use the following modifiers:
|%%~A||%~1||expands %%A or %1, removing any surrounding double quotes (“)|
|%%~fA||%~f1||expands %%A or %1 to a fully qualified path name|
|%%~dA||%~d1||expands %%A or %1 to a drive letter only|
|%%~pA||%~p1||expands %%A or %1 to a path only|
|%%~nA||%~n1||expands %%A or %1 to a file name only|
|%%~xA||%~x1||expands %%A or %1 to a file extension only|
|%%~sA||%~s1||expanded path contains short names (8.3 filename syntax) only|
|%%~aA||%~a1||expands %%A or %1 to file attributes of file|
|%%~tA||%~t1||expands %%A or %1 to date/time of file|
|%%~zA||%~z1||expands %%A or %1 to size of file|
|%%~$PATH:A||%~$PATH:1||searches the directories listed in the PATH environment variable and expands %%A or %1 to the fully qualified name of the first one found. If the environment variable name is not defined or the file is not found by the search, then this modifier expands to an empty string.|
An extremely useful application of this is in the initialization of a script, to make sure that the current directory is changed into the location where the script is stored.:
Another handy one-liner to have is this one. It will locate program SETX.EXE via directories named in the PATH (Note: This syntax is for entering it in an interactive command window):
for %I in (setx.exe) do echo %~$PATH:I
Notes on double quotes in file names and best use practices
- Always use the removal of the quotes using %~1 when using PVARs. This way, you can be sure that quotes are only used when you pass the variable to another subroutine or batch file, and that you never pass double double quotes (e.g. “”variable””). This will inevitably happen if you ever need to address files which have a space in their fully qualified path name.
- When storing a path in an MVAR, do not use double quotes. The variable will contain the spaces anyway, and using double quotes makes concatenating paths and file names difficult. Instead, only use the double quotes on the place where the value is passed to a command that requires them.
Example: Save the following lines in a file %TEMP%test.bat
rem This will cause problems: for %%A in ("%1") do echo %%A rem This is the proper syntax: for %%A in ("%~1") do echo %%A
Then, execute the following command from a CMD shell:
%TEMP%test.bat "c:\documents and settings\default user"
You will see, that the (necessary) quotes are in the %1 parameter, and therefor the first FOR loop fails to display the expected text.
MVAR: Retrieving substrings
set FIRST_3_CHARS=%PATH:~0,3% set LAST_3_CHARS=%PATH:~-3% set ALL_BUT_LAST_3_CHARS=%PATH:0,-3%
Unfortunately, it is not possible to use a variable for the offset or the count.
MVAR: Counting using environment variables
set /a AVAR+=1 set /a AVAR2=%AVAR%+10
set ODD=1 for /l %%I in (1,1,5) do set /a ODD+=2 echo %ODD%
Special variables in the environment
|%CD%||expands to the current directory string|
|%DATE%||expands to current date using same format as DATE command|
|%TIME%||expands to current time using same format as TIME command|
|%RANDOM%||expands to a random decimal number between 0 and 32767|
|%ERRORLEVEL%||expands to the current ERRORLEVEL value|
|%CMDEXTVERSION%||expands to the current Command Processor Extensions version number|
|%CMDCMDLINE%||expands to the original command line that invoked the Command processor|
Special system variables in Windows 2000/XP/Vista
Note: This list can be obtained by executing the SET command without parameters.
|Variable name||Typical value|
|%ALLUSERSPROFILE%||C:Documents and SettingsAll Users|