Quoted here in full because MSDN archives tend to be somewhat unreliable:
The easy way is to use the %CD% pseudo-variable. It expands to the
current working directory.
set OLDDIR=%CD% .. do stuff .. chdir /d %OLDDIR% &rem restore current directory
(Of course, directory save/restore could more easily have
been done with pushd/popd, but that's not the point here.)
The %CD% trick is handy even from the command line. For example, I
often find myself in a directory where there's a file that I want to
operate on but... oh, I need to chdir to some other directory in order
to perform that operation.
set _=%CD%\curfile.txt cd ... some other directory ... somecommand args %_% args
(I like to use %_% as my scratch environment variable.)
Type SET /? to see the other pseudo-variables provided by the command
processor.
Also the comments in the article are well worth scanning for example this one (via the WayBack Machine, since comments are gone from older articles):
This uses the batch parameter extension syntax. Parameter 0 is always the script itself.
If your script is stored at C:\example\script.bat, then %~dp0 evaluates to C:\example\.
ss64.com has more information about the parameter extension syntax. Here is the relevant excerpt:
You can get the value of any parameter using a % followed by it's numerical position on the command line.
[...]
When a parameter is used to supply a filename then the following extended syntax can be applied:
[...]
%~d1 Expand %1 to a Drive letter only - C:
[...]
%~p1 Expand %1 to a Path only e.g. \utils\ this includes a trailing \ which may be interpreted as an escape character by some commands.
[...]
The modifiers above can be combined:
%~dp1 Expand %1 to a drive letter and path only
[...]
You can get the pathname of the batch script itself with %0, parameter extensions can be applied to this so %~dp0 will return the Drive and Path to the batch script e.g. W:\scripts\
This answer will also work if the batch file is invoked without an explicit path!
First the script determines if the batch file was called with a path. If that's the case that path is used. If not, the %path% is searched to find the batch file.
@echo off
setlocal enableextensions enabledelayedexpansion
for /f %%i in ('cd') do set CURDIR=%%i
set LAUNCHERPATH=%~dp0
if "%LAUNCHERPATH%" neq "%CURDIR%\" goto LAUNCHERPATHOK
set LIST=%PATH%
:ProcessList
for /f "tokens=1* delims=;" %%a in ("!LIST!") do (
if "%%a" neq "" (
set x=%%a
IF EXIST "%%a%0.bat" GOTO FOUND1
IF EXIST "%%a\%0.bat" GOTO FOUND0
IF EXIST "%%a%0" GOTO FOUND1
IF EXIST "%%a\%0" GOTO FOUND0
)
if "%%b" NEQ "" (
set List=%%b
goto :ProcessList
)
)
exit 1
:FOUND0
set x=%x%\
:FOUND1
set LAUNCHERPATH=%x%
:LAUNCHERPATHOK
echo %LAUNCHERPATH%