Introduction
Setting environment variables within Windows and DOS has always been simple (e.g., set foo=bar). However, sometimes it is desirable to take the output of a command and set it to an environment variable, and here is where things get more difficult. I scoured the web back in 2002 or so trying to find easy methods to accomplish this, and nothing worked all that well. Later on, through more searching, I found one excellent tool for accomplishing this task (setenv.exe), and found a second method while experimenting with the FOR command (and reading FOR help).
Setting environment variables from stdout of another program or command:
- The easiest solution to this problem is to use setenv.exe (originally from LS Tools, which has been deprecated). You can set variables directly, from stdout of another program, and from stderr. LS Tools are free, btw, and work on all win32 platforms.
- The cleanest solution (clean because it does not require the use of a 3rd party application) is to use the FOR command. This command has become more and more powerful as Windows has developed, so this solution will not work for all versions. It should work on Windows 2000 and later, but be sure to experiment to verify.
- Basic example: the following example will set the variable FOO with the output from the 'cd' command.
for /f %a in ('cd') do set foo=%a - More advanced example: from a batch file, this example snags sets the variable FOO to only part of the output from the 'filever' command (a 3rd pary utility that snags file version data).
I actually called the above FOR statement as a subroutine (:VerCheck) from another FOR statement, hence the use of %1 with the filever.exe command. This first FOR command parses a text file containing the data I want to manipulate, and looked like so:
for /f "tokens=5,6" %%a in ('.\filever.exe %1') do set foo=%%afor /f "eol=;" %%i in (.\list.txt) do call :VerCheck %%i - The command to be executed that produces stdout (and thus used as stdin) must be within `back ticks`, which is required for the OS to understand that the entry within the ticks will get executed. You must also use the "usebackq" flag. It is this feature that is not supported by all versions of Windows (and not supported in DOS). It does not really matter what commands are within the ticks; experiment with it. HOWEVER, certain functions used within the ticks (pipe [ | ], redirects [ > ], etc.) require the use of a caret [^ ] as an escape character, and possibly the use of the "usebackq" flag. For example:
for /f "usebackq tokens=2* delims=:" %a in (`ipconfig ^| find /i "IP Address"`) do for %b in (%a) do set IP_Address=%b - In the above example, the nested FOR statement removes the extra white space, which is often useful.
- Basic example: the following example will set the variable FOO with the output from the 'cd' command.
Things to keep in mind:
- Command Extensions have to be enabled for most of the cool FOR and SET functions to work properly. They are enabled by default in Windows 2000 and later, but I am unsure about NT 3.5/3.51/4.0, and don't think Windows 95/98/ME support it at all.
- Variables are easily manipulated with Windows 2000 and later via the command shell. You can perform arithmetic operations, unary operations, etc. Type "help set" at the command prompt to learn more about this.
- When using FOR commands within a batch file, you need to use double percent signs, like so:
for /f %%a in ('cd') do set foo=%%a - In general, backticks and the usebackq flag are preferred when using the FOR command to process commands. So, for the above command, it would look like so:
for /f "usebackq" %%a in (`cd`) do set foo=%%a - When snagging specific parts of the output, the "tokens" flag is useful, which will assign data to sequential variables (%%a, %%b, %%c, etc.). However, sometimes you may want to have a single variable contain multiple tokens. This is done by defining "tokens=*" to get all tokens, or "tokens=2*" to get all tokens starting at the second token. When this doesn't work (as sometimes happens), I have found that defining a non-default delimiter meets my needs. This works because the default delimiters are "space" and "tab." If I define different delimiter, the defaults are not used, and I can snag multiple items without issue. Here are examples:
for /f "usebackq tokens=*" %i in (`sc query w32time^|find "STATE"`) do set foo=%ifor /f "usebackq tokens=2 delims=:" %i in (`sc query w32time^|find "STATE"`) do set foo=%i - You can nest FOR statements, as needed. This is done like so:
for /f "delims=/" %%a in (file.txt) do ( for %%b in (%%a) do ( if not %%b==FI for /f "delims=" %%c in (%%b) do echo %%c>>file2.txt ) ) - When setting variables within a batch file, start your script with setlocal and end it with endlocal so that you don't write over any existing environment variables. Check "help setlocal" and "help endlocal" for more details.
- SS64-esc and SS64-redirection are a great sites for more syntax coolness.