in

ASP.NET Weblogs

Loren Halvorson's Blog

If your only tool is a hammer...

Silly batch file tricks, redirecting stdout into an evironment variable and %~dp0

Some things in batch files seem like they should be so simple, but I'm embarrassed to say how long it took to come up with this little trick. Maybe YOU knew it already, but you should have posted it in your blog so I could have googled it and been done in the 10 seconds it SHOULD have taken me to solve it :-)

In case you ever have wanted to take the console output of a command line tool and capture it in an environment variable, this works. There may be better ways. Thanks to Scott Colestock for helping dig this one up.

setlocal
sometool.exe > temp.txt
set /p TOOLOUTPUT= < temp.txt
del temp.txt
..do something with %TOOLOUTPUT%...
endlocal

Of course when Monad comes out none of this monkey business will be necessary. By the way, I just listened to another great Hanselminutes podcast on Monad that has convinced me to give it a whirl http://www.hanselminutes.com/default.aspx?showID=12.

Since I'm on the topic of useful/(or useless?) batch file tricks, another little known one I find myself using alot is the "%~dp0" macro which resolves to the fully expanded path to the directory containing the batch file. This allows batch files to run regardless of the current working directory. So for example Visual Studio post build events run with the current working directory set to bin\Debug or (bin\Release). But you probably have the postbuild.bat file sitting up a couple directories along side the csproj/vbproj project file. So adding a %~dp0 in front of things you do in the batch file give you location independence without having to do hard-coded paths or a lot of  ..\..'s all over the place. So the following will always find the "sometool.exe" sitting right next to the batch file no matter where it's run from.

setlocal
"%~dp0sometool.exe" > temp.txt
set /p TOOLOUTPUT= < temp.txt
del temp.txt
..do something with %TOOLOUTPUT%...
endlocal

Comments

 

Joe said:

You can also avoid the temp file by using:

FOR /F "tokens=*" %%i in ('%~dp0sometool.exe') do SET TOOLOUTPUT=%%i

The CMD.EXE command processor is actually quite powerful, if a little unintuitive (e.g. to suppress prompting, DEL uses /Q but XCOPY uses /Y). If you write batch files, it's worth getting a cup of coffee and spending 1/2 hour in front of a command prompt with FOR /?, SET /? etc.
March 24, 2006 3:39 PM
 

BambooWave said:

Thanks Loren, %~dp0 enables our BizTalk setup/cleanup batchfiles to be run via Nant and the great CruiseControl.

August 9, 2006 7:59 AM
 

Dennis said:

I don't see why Monad will remove the need for these tricks if WSH hasn't managed to do so...

October 22, 2006 4:38 AM
 

Steve said:

Here are some more neat tricks for XP:

http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/percent.mspx?mfr=true

http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr=true

%0 is the name of the batch file, so the %~dp0 is extracting the path, to get only the batch file's name you can use: %~nx0

/Steve

November 7, 2006 12:30 AM
 

Anil said:

Great!

It really helped me!

April 27, 2007 5:15 AM
 

Stl said:

No offense lads but both "SET /P" or the "FOR /F" monster look frigtening compared to UNIX backquotes :-)

June 11, 2007 12:49 PM
 

suryakant said:

Thanks a lot.................. it really help me....; )

June 13, 2007 5:37 AM
 

Shortcut said:

Just the kind of "shortcut" i needed!

Thanks!

:o)

July 23, 2007 4:30 AM
 

Andamo said:

So I found this blog by looking for a way to have the actual command piped to a file as well as the results.

for /F "tokens=1 delims=" %% in (users.txt) do (command "%%S") >> outputfile.txt

I would like the actual command piped as well, in this case the users name.

Any ideas?

August 16, 2007 11:21 AM
 

Timbo said:

for /f "tokens=1 delims=" %%s in (users.txt) do (echo %%S & command "%%S") >> outputfile.txt

September 24, 2007 9:57 PM
 

prx64 said:

THANKS A LOT !!! I was digging into google looking for such a basic script  !!!!

batch is _really_ not bash ;-)

November 20, 2007 7:32 AM
 

Yako said:

So if set/p captures a line of standard input, then I would expect this to work, but it doesn't seem to:

dir | set /p outputfromdir=

Any ideas why?

March 11, 2008 11:47 AM
 

Arun said:

Batch File output Redirection:

I want to redirect the output of my batch file to a .txt/.doc/.xls file.

For that I am using the syntax:

“C:\ProjFolder\Application.exe > Logfile.txt” and saved it as a batch file.

My Log file is supposed to hold several 1000 lines of data.

But my problem is that after certain limit, no data is going into the Logfile.

Somebody please tell me the reason???

April 4, 2008 7:51 AM
 

andres said:

i found this which works for my needs and seems way easier:

ENV_VAR=`program.exe`; echo $VMID

found it here: ubuntuforums.org/showthread.php

May 6, 2008 5:36 AM
 

markc said:

I'd like to capture the current time more accurately than time/t allows. Set prompt=$T gives the time in 24 hour to hundredths of a second and is just what I want.

June 1, 2008 8:52 PM
 

sascha said:

@andres that's for bash, not batch (ie. linux, not windows)

But you're right, it's waaaay easier - hence why my build scripts are a mix of bash files (cygwin) and batch files (windows)

June 5, 2008 8:40 PM
 

dp0 script macro said:

Pingback from  dp0 script macro

June 24, 2008 6:06 AM
 

Sameer Dhoot said:

This helped me. I am using this in Automated setup scripts for Sahrepoint using PSCONFIG and STSADM. I have lot of files in different directories which were needed to be installed by this script. I have to run this script from the lcation where it was stored.

This post helped me in getting location independence and included this script in Windows directory so call it from anywhere this is what is use

pushd .

cd %~dp0

..... automated script for sharepoint installation.....

popd

Thanks and Regards,

Sameer Dhoot.

August 11, 2008 2:16 PM
 

Alexei said:

Hi,

I need to work with legacy batch files, and I am trying to figure out an easy way to check if a task is currently running. I am planning to put the batch job in scheduler and only run a task if it's not running.

August 12, 2008 2:38 PM
 

Hedles said:

Alexei,

What version of Windows are you running?

If it's XP, you can get a list of processes with tasklist.  It may work with Vista, too, but I don't think in 2k.

I'd use GNU sed to grab the process/line you want.  It doesn't seem to glue very well to tasklist if you try to pipe the output straight into sed, but you can send the process list to a file first, then sed will do fine.

If you have Powershell aka ps (aka Monad aka msh), you can use get-process.

August 19, 2008 4:05 PM
 

Ken said:

The parms do not work for Telnet

Does anyone know why?

Telent does not output anything to Temp.TXT

setlocal

Telnet.exe xxx 443 > temp.txt

set /p TOOLOUTPUT= < temp.txt

del temp.txt

..do something with %TOOLOUTPUT%...

endlocal

September 9, 2008 12:17 AM
 

Eric said:

Holy crap. THANK YOU.

I'd been trying to capture program output to variable for a good couple of hours before I came across your web page.

This is a god send.

Cheers.

Eric

September 19, 2008 5:48 PM
 

SAM's Wiki: Windows links said:

Pingback from  SAM's Wiki: Windows links

September 28, 2008 5:44 AM
 

Tai said:

Thanks for the blog, it was promising, and almost worked for me, but....

This line:

set /p TOOLOUTPUT= < temp.txt

only seems to accept a certain number of characters from temp.txt -- after that maximum is reached, the string inside temp.txt gets cut off.

The workaround I found was to build temp.txt right into a batch script i.e. temp.txt for me contained 500 arguments to a program, so temp.bat called that program with the arguments.

December 15, 2008 1:40 AM
 

sachin said:

I am interested to learn batch programing..

December 26, 2008 3:52 AM
 

subha said:

Nice code.

This is what exactly i  am looking for.

Thanks  a lot

February 9, 2009 4:24 AM
 

Gerald said:

With the command line tool Export.exe you can put the stdout output of win32 console programs into CMD.EXE environment variables, which is very useful for batch files

Example: Read the current date from stdout and put it into an environment variable (Attention: use backquotes!).

C:\tmp>export.exe DATEVAR=`date /t`

C:\tmp>echo %DATEVAR%

25.02.2009

see www.xeox.com/index.php

February 25, 2009 8:56 AM
 

Timestamp said:

nice aswel is timestamp environment var to spool to a timestamped batch file

:: sets the timestamp arguments to the actual date & time

for /f "tokens=1,2 delims=: " %%i in ('time /t') do set hhmi=%%i%%j

for /f "tokens=2,3,4 delims=/- " %%i in ('date /t') do set yyyymmdd=%%k%%j%%i

set log_backup_changes=%yyyymmdd%-%hhmi%_backup.log

rman target / @%script_backup_changes% log=%log_backup_changes% append

March 3, 2009 9:14 AM
 

ChernoJ said:

Date and Time: Instead of date /t and time /t, there're the built-in %date% and %time% env vars.

eg:

echo %time%

set timestamp=%date% %time%

March 13, 2009 3:01 AM
 

Maddy said:

Hi,

Can anyone suggest a method by which we can extract the output or the contents of an IDE to a text file.

A batch file named run.bat calls the IDE under test.

Thanks

Maddy

April 15, 2009 8:14 AM

Leave a Comment

(required)  
(optional)
(required)  
Add