How to: Creating a unique temporary file and determining the working drive and path
This is a demonstration of how to use a TempFile in a .BAT or .CMD file. The goal of this example is to determine the relative path of the current working directory and assign it to a variable.
Concepts Demonstrated:
- Generating a unique file names
- Creating a temp file, using the Windows Naming convetion, and deleting it when done
- Calling support subroutines in a batch file
- Using GOTO :EOF to end exit a subroutine but not the batch file
- Use of the command line “FOR” routine
- Using Variables with “for /F”
- How to get the current directory
- Verbose and Quiet modes for a batch file
Temporary files are incredibly useful in batch files. When used in combination with a “For” loop, you can accomplish some amazing stuff from the command line.
In this example we assign a new file name to the TEMPORARY_FILE variable and then export the current working path to that file by echoing cd environment variable to it:
call :GETTEMPNAME
echo %cd%>%TEMPORARY_FILE%
Once our temp file has contents, the For routine can be used to parse each line and execute a command with the result. So, we use the For command to divide the working directory, lets say it is “C:\WorkingDir” into several peices (aka tokens):
FOR /F “tokens=1* delims=:” %%G IN (%TEMPORARY_FILE%) DO set RelativePath=%%H
Literaly we are telling it to break the line up at every colon ( : ), and to assign the first token to the variable %G. The asterisk (*) indicates that each token after that should be assigned to a new variable letter (H,I,J, and etc.). In our example, our %H will contain “\WorkingDir”.
“For /F” is really most usefull with larger files containing multiple lines. Since our file contains only one line with two tokens, the process stops there but you could, for example, parse all the names of files in a directory (dir *.xyz /b > %TEMPORARY_FILE%), or the contents of a registry key exported to that file using (REG QUERY […] > %TEMPORARY_FILE%). I’ve used both of these methods in the past to do some really neat things that might have otherwise involved creating a custom executible. One advantage of doing it from teh command line is that it keeps the registry clean of all the garbage left behind by Windows anytime you run an exe.
Oh!
Something that is not often emphasized in “For /F” documentation is that it can parse variables as well as files. This could greatly optimize this example. Instead of parsing our file, we would simply put our %CD variable in quotes and call:
FOR /F “tokens=1* delims=:” %%G IN (“%CD%”) DO set RelativePath=%%H
We will get exactly the same results and can cut our batch file size in half! Of course, then we wouldn’t have a good example of temp file usage would we? So, we will do it the hard way.
Thus:
http://www.thecodecave.com/downloads/batch/GetRelativePath.bat
[DOS]
@Echo Off
::*************************************************************************
:: This is a demonstration of TempFile usage, Batch Subroutines, using
:: the FOR loop to parse parameters, Goto :EOF, using parameters to
:: control the Verbose or Quiet execution of a batch routine, getting the
:: local directory from an environment variables and the use of long
:: comments in a batch file.
::
:: Usage:
:: GetRelativePath <-- Shows the essential output
:: GetRelativePath Verbose <-- Shows all of the work
::
:: This routine is pretty simple. It gets a guaranteed unique temporary
:: filename uses it and then puts the current path in that file. It then
:: use the For command to break that path into peices at the colon and
:: put the second chunk in an environment variable. That all could be
:: done with the for loop parsing the local variable, but then we
:: wouldn't have an example of using a temp file would we?
::
:: Original Author - Brian Layman
::
:: Created - 01/APR/2006
:: Last Modified - 01/APR/2006
:: Contributors: (Put your name & Initials at the top)
:: Brian Layman - BL - http://www.TheCodeCave.com
::
::
:: History:
:: 01/APR/2006 - BL - Created
::
:: License - If this helps you - Great! Use it, modify it share it.
::
:: Indemnity -
:: Use this batch file at your own risk. I'm only calling built-in Windows
:: commands, but if a typo or service pack change affects what this routine
:: does, it is not my fault. In fact, you should just stop right now and
:: not run this file. For if it causes blue smoke to be emitted from your
:: network card, if it resets your home site to HowToKillMyBoss.com, or if
:: it makes your sister break up with her lawyer boyfriend and start dating
:: a caver, it is not my fault. (Actually that last one might be an
:: improvement, but it is still not my fault.)
::
:: Donations - If this batch file really helps you out, feel free to make a $5
:: (US) donation via Paypal to Brian@TheCodeCave.com or just send a Thank
:: You via email to that address and include your country of origin.
:: ::*************************************************************************
:: *************************************************************************
:VerboseCheck
:: Check for the Verbose password.
:: *************************************************************************
:: Put a bracket around the %1 to trap for empty values and to allow the
:: string comparison to work
if NOT [%1] == [Verbose] GOTO :TheWorks
echo On
:: *************************************************************************
:: *************************************************************************
:TheWarning
::
:: Normally a Quiet variable would display some info about the program
:: and also allow several ways to abort an accidental launch, but this
:: example uses a verbose command to make it show all of the work.
::
:: *************************************************************************
Echo Maximum Verbosity.
Echo Hit Ctrl+Break now to stop here or just
@pause
:: *************************************************************************
:TheWorks
::
:: Let the fun begin!
::
:: *************************************************************************
if NOT [%1] == [Verbose] @Echo off
Echo Generating Temp name
if [%1] == [Verbose] Echo *************************************************************************
call :GETTEMPNAME
if [%1] == [Verbose] Echo *************************************************************************
Echo.
Echo Temp name is %TEMPORARY_FILE%
Echo.
Echo Current Directory is %cd%
Echo.
Echo The next process strips the drive designation off and stores the new value
:: Strip off the Drive letter for the server path
:: This involves some fancy footwork with a temp file and a For statement.
call :GETTEMPNAME
if [%1] == [Verbose] Echo *************************************************************************
:: Send the current path out to a temp file so that it can be used with FOR /F statements
echo %cd%>%TEMPORARY_FILE%
FOR /F “tokens=1* delims=:” %%G IN (%TEMPORARY_FILE%) DO set RelativePath=%%H
if [%1] == [Verbose] Echo *************************************************************************
Echo.
Echo The relative path is %RelativePath%
:: *************************************************************************
:TheEnd
::
:: So long and thanks for all the fish!
::
:: *************************************************************************
Echo.
pause
GOTO :EOF
Echo.
:: *************************************************************************
:: Support procedures
::
:: These routines are called with a CALL directive and the GOTO :EOF
:: terminates that CALL but does not terminate the entire running of the
:: batch file.
:: *************************************************************************
:: *************************************************************************
:: GETTEMPNAME procedure
:: Create a temporary file name guaranteeing the file doesn’t exist
::
:: Returns: TEMPORARY_FILE=Temporary file name
::
:: *************************************************************************
:GETTEMPNAME
if not defined _NEXTTEMP set /a _NEXTTEMP=1
:GETTEMPNAMELOOP
if defined TEMP (
(set TEMPORARY_FILE=%TEMP%)
) else if defined TMP (
(set TEMPORARY_FILE=%TMP%)
) else (set TEMPORARY_FILE=%SystemRoot%)
set /a _NEXTTEMP=_NEXTTEMP * 214013 + 2531011
set /a _T1=_NEXTTEMP ^>^> 16 ^& 0x7FFF
set TEMPORARY_FILE=%TEMPORARY_FILE%\~SH%_T1%.tmp
if exist “%TEMPORARY_FILE%” GOTO :GETTEMPNAMELOOP
set _T1=
GOTO :EOF
:: *************************************************************************
[/DOS]