2009-04-29

DOS Command Substitution

I have written many scripts in shell script (Bash mostly). By no means am I an expert in shell, but I like its power.

So when I have to do stuff in DOS, I feel powerless. DOS is such a poor and restricting environment for the unlucky shell programmer.

My pet peeve has been the lack of command substitution:

$ variable = `command`

where the variable is assigned the output from the executed command.


Well, as it turns out, it is possible to do something similar in DOS. It is just not very simple to do (in comparison).

Have a look at the FOR documentation. The /F variant allows you to execute a command. The output is assigned to a temporary variable, which can then be accessed in the loop part.

For example, assign the date to the variable TODAY with:

DOS> FOR /F "usebackq delims=^" %i IN (`date /t`) DO @set TODAY=%i

(yes, I know of %DATE% - it is an example!)

Two notes:
  1. the delims character must not appear in the output
  2. if you use it in a script, replace %i with %%i.

It would be a stretch to call it elegant. But it works.


I have also used one of the other FOR /F variants for reading values from a property file (using = for key/value separation):

DOS> FOR /F "usebackq delims== tokens=1,2" %i IN (c:\temp\file.properties) DO set PROP_%i=%j

Here FOO=BAR in the file will result in %PROP_FOO% being assigned the value BAR.

2 comments:

  1. No, not elegant, but certainly much better than my usual approach: Build a temporary bat file with the desired assignment a execute it with call...

    ReplyDelete
  2. I struggled to find a solution, and i finally bumped into http://ss64.com/nt/call.html

    use the following:
    call set varValue=%%varName%%

    for example:
    C:\>set myVar=hello
    C:\>set myRef=myVar
    C:\>call set lololol=%%myRef%%
    C:\>echo %lololol%
    hello

    YEAHHHHH !!!!

    <<
    Advanced usage : CALLing internal commands

    In addition to the above, CALL can also be used to run any internal command (SET, ECHO etc) and also expand any environment variables passed on the same line.

    For example

    @ECHO off
    SETLOCAL
    set server1=frodo3
    set server2=gandalf4
    set server3=ascom5
    set server4=last1

    ::run the Loop for each of the servers
    call :loop server1
    call :loop server2
    call :loop server3
    call :loop server4
    goto:eof

    :loop
    set _var=%1
    :: Evaluate the server name
    CALL SET _result=%%%_var%%%
    echo The server name is %_result%
    goto :eof

    :s_next_bit
    :: continue below

    :: Note the line shown in bold has three '%' symbols
    :: The CALL will expand this to: SET _result=%server1%
    Each CALL does one substitution of the variables. (You can also do CALL CALL... for multiple substitutions)

    If you CALL an executable or resource kit utility make sure it's available on the machine where the batch will be running, also check you have the latest versions of any resource kit utilities.

    If Command Extensions are disabled, the CALL command will not accept batch labels.

    "My mother never saw the irony in calling me a son-of-a-bitch." - Jack Nicholson
    >>

    ReplyDelete