Wednesday, January 26, 2011

Consistent Usage of Relative Paths in .bat Scripts

Seeing as I haven't posted anything in a while, I figured I'd post this example script demonstrating a simple to implement feature that makes it a lot easier to manage paths to your script's files (assuming you're using a script that depends on other files ;).

I find it quite annoying when I'm one directory away from a script I need to run, but calling `..\myScript.bat` results in tons of "..\callingDir\someScriptFolder not found" errors.

For this reason, I make it a point to cd to the script's directory when messing around with relative paths. The only problem with a straightforward cd is that once the script has finished running, you're left stranded in a folder in the middle of nowhere (assuming it's not just up a single directory).

The following example demonstrates storing the directory the script was called from, cd'ing to the script's directory, doing some stuff, and switching back to the original directory. It's nothing too special, but I find it quite useful.

REM Example script - changes to script directory then back to calling dir
@echo off
setlocal

REM Check if no arg was given
if "%1"=="" goto :printUsage

REM Check if copy-to directory isn't a valid dir (see usage)
if not exist %1\ goto :badArg

REM Store current directory and cd to script dir
set CALLING_DIRECTORY=%cd%
cd /d %~dp0

REM Copy files
copy copyTheseFiles\* %1

REM cd back to directory script was called from
cd /d %CALLING_DIRECTORY%

REM Exit successfully
goto :EOF

REM Print an error message
:badArg
echo Error locating folder^: %1
goto :EOF

REM Print the script's usage
:printUsage
echo Usage^: %0 [dir to copy stuff to]

:EOF
endlocal



One of my earlier posts: 'Listing Hidden Files in Bash, provides a more specialized example of doing the same thing in a bash script.

If you've read this far past the example, you may be interested in the setlocal and endlocal calls I've included. These prevent the environment variable CALLING_DIRECTORY from leaving the scope of the script and polluting your command prompt's environment.

I should probably also note that the %~dp0 uses the tilde argument d and p on variable 0 (the first argument (or name of the script)). The tilde 'operator' (if it can rightly be called that) can be used to perform expansions on the variable (in this case d (drive) and p (path)). More information on this can be found at the 'help' page for 'for' (`help for`). I've found it annoying that you can only use this with single letter variables (ie. command line arguments or variables in for loops), but what can you expect from the backwards-ass batch scripting language if not it's inconsistency?
Anyway...

That's all for now,
Happy scripting!

No comments:

Post a Comment