Wednesday, March 29, 2006

Directory management in... batch files!

Ok, consider it the only way I found to look original: It's 2006 and you're reading about cmd.exe and batch files tricks ;-)

I usually use JScript WSH scripts to automate tasks but occasionally batch files simply remain the best choice. It's especially true when what you need to do mostly consist in running a sequence of command-line programs.

I recently wrote a set of batch files that run programs located in the same directory (or in sub-directories, or in sibling directories. Whatever.) and the data files they manipulate are also in this directory. Pretty straightforward : use no paths (or relative paths) when specifying the programs and files locations.

The problem...

The problem is you assume that the current working directory (CWD) is the directory where your batch file is located.

How to make sure the current working directory is correctly set ?

One way is to invoke the batch files using a shortcut: You can set the directory in there.
Hmm... Not very general a solution! What I want is to be able to run the batch file by double-clicking it in Explorer or by typing its full path in a command prompt.

Let's look for something better, such as maybe batch files argument specifier %0. No, not good: It yields the name of the batch file but not the path.

The solution

Here's something better: %~dp0. This converts to the (drive and directory) path of the batch file. Kewl! We can now add this statement at the top of our batch file to set the current directory:

cd %~dp0
Not bad. But there's still a problem: if you start from another drive, cd won't change the current drive letter. You'll want to use the /d (d stands for drive) to fix this issue:

cd /d %~dp0
Note that %~dp0 contains a trailing backslash. Therefore, you can use it in such combinations

cd /d %~dp0MySubDir
This sets the CWD as sub-dir MySubDir of the directory where the batch file is located.

Did you receive a good education ?

If yes, you'll want to set the CWD back to its original value when you're done.

Solution1 (bad. Think of the mess when you have nested batch files.):

SET OriginalDir=%CD%
cd /d %~dp0
DoStuff
cd /d %OriginalDir%
%CD% is a pseudo environment variable that yields the curent directory.

Solution 2 (Much nicer):

pushd %~dp0
DoStuff
popd
pushd pushes the CWD and switches to the specified one (including drive letter).
popd restores the previously pushed directory.
Neat! No temp environment variables. Works like a charm with nested batch files.

Nested batch files

Just a reminder: don't forget to use call to invoke a batch file from another one. The trap is that you don't have to use call to execute another batch. But if you don't, the rest of the caller file will not be executed :-(

Note to Self

MONAD MSH. Will I really wait another year before giving it a look...

4 Comments:

At 9:59 PM, Anonymous Anonymous said...

Thanks Serge :) This was very helpful!

 
At 9:33 AM, Anonymous Daniel Lohmann said...

By using pushd and popd you get another very nice feature as well: They can (as opposite to cd) "change" into directories given as an UNC path.

If one tries something such as

cd \\COOLSERVER\DUMBSHARE

cmd.exe prints an error message that it doesn't support UNC paths (which is, actually, a shame, a shame, a shame!)

However

pushd \\COOLSERVER\DUMBSHARE

works. The trick is that, given an UNC path, pushd automatically selects a free drive letter, connects it to the share, changes the current drive and switches into the directory. If the directory is left with popd, the connection is canceled and the drive letter freed.

Hence, your batch now most probably works even if located on an UNC share :-)

 
At 11:07 PM, Anonymous Jive said...

Nice one, thanks :) used it to help me copy firefox bookmarks file to another directory without knowing the profile folder title and it doesn't matter where I run it from:

set thisdir=%~dp0
...do stuff elsewhere...
cd /d %thisdir%
...finish up...

 
At 9:42 PM, Anonymous Anonymous said...

Magician alone [url=http://itkyiy.com/lasonic-lta-260/]lta chile[/url] rlene smiled [url=http://itkyiy.com/methylprednisolone-acetate/]methylprednisolone and alcohol[/url] hollow eye [url=http://itkyiy.com/sces/]sce discounts[/url] something bad [url=http://itkyiy.com/k-chlor/]atenolol chlor[/url] much more [url=http://itkyiy.com/epipen-online-video/]epipen and production and cost[/url] had hoped [url=http://itkyiy.com/bio-identical-estrogens/]overweight women estrogens hairy[/url] isle looked [url=http://itkyiy.com/vertigo-meclizine/]side effects of meclizine[/url] and get [url=http://itkyiy.com/goody's-credit-card-bill/]goody's warn notice[/url] the completion [url=http://itkyiy.com/sodium-xylene-sulfonate/]barium diphenylamine sulfonate[/url] human genes [url=http://itkyiy.com/technetium-99m/]technetium ecd[/url] large but [url=http://itkyiy.com/siberian-ginseng-increasing-testosterone/]ginseng and medicine[/url] one the [url=http://itkyiy.com/dr-jonas-salk-biography/]salk contemporary[/url] arrow cage [url=http://itkyiy.com/fond-du-lac-reservation-tribal-enrollment/]fond du lac wi newspaper[/url] own eyes [url=http://itkyiy.com/tramadol-vs-vicodin/]online pharmacy vicodin hydrocodone[/url] the ceiling [url=http://itkyiy.com/removing-chlorine-with-sodium-thiosulfate/]sodium thiosulfate vs hydrochloric acid[/url] young woman [url=http://itkyiy.com/peekaboo-petites/]cleo petites[/url] old child [url=http://itkyiy.com/tummy-tucks-brooklyn/]table that tucks into sofa[/url] weighed more [url=http://itkyiy.com/turbo-backup-pep/]pep plus turbo backup[/url] exiled one [url=http://itkyiy.com/diphenhydramine-lawsuits/]diphenhydramine hcl for sleep[/url] the dusky [url=http://itkyiy.com/ethyl-epa-purified/]purified compressed air[/url] properly appreciate attanes.

 

Post a Comment

<< Home