Resolve absolute path from relative path and/or file name
Is there a way in a Windows batch script to return an absolute path from a value containing a filename and/or relative path?
Given:
"..\"
"..\somefile.txt"
I need the absolute path relative to the batch file.
Example:
- "somefile.txt" is located in "C:\Foo\"
- "test.bat" is located in "C:\Foo\Bar".
- User opens a command window in "C:\Foo" and calls
Bar\test.bat ..\somefile.txt
- In the batch file "C:\Foo\somefile.txt" would be derived from
%1
In batch files, as in standard C programs, argument 0 contains the path to the currently executing script. You can use %~dp0
to get only the path portion of the 0th argument (which is the current script) - this path is always a fully qualified path.
You can also get the fully qualified path of your first argument by using %~f1
, but this gives a path according to the current working directory, which is obviously not what you want.
Personally, I often use the %~dp0%~1
idiom in my batch file, which interpret the first argument relative to the path of the executing batch. It does have a shortcoming though: it miserably fails if the first argument is fully-qualified.
If you need to support both relative and absolute paths, you can make use of Frédéric Ménez's solution: temporarily change the current working directory.
Here's an example that'll demonstrate each of these techniques:
@echo off
echo %%~dp0 is "%~dp0"
echo %%0 is "%0"
echo %%~dpnx0 is "%~dpnx0"
echo %%~f1 is "%~f1"
echo %%~dp0%%~1 is "%~dp0%~1"
rem Temporarily change the current working directory, to retrieve a full path
rem to the first parameter
pushd .
cd %~dp0
echo batch-relative %%~f1 is "%~f1"
popd
If you save this as c:\temp\example.bat and the run it from c:\Users\Public as
c:\Users\Public>\temp\example.bat ..\windows
...you'll observe the following output:
%~dp0 is "C:\temp\"
%0 is "\temp\example.bat"
%~dpnx0 is "C:\temp\example.bat"
%~f1 is "C:\Users\windows"
%~dp0%~1 is "C:\temp\..\windows"
batch-relative %~f1 is "C:\Windows"
the documentation for the set of modifiers allowed on a batch argument can be found here: https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/call
I came across a similar need this morning: how to convert a relative path into an absolute path inside a Windows command script.
The following did the trick:
@echo off
set REL_PATH=..\..\
set ABS_PATH=
rem // Save current directory and change to target directory
pushd %REL_PATH%
rem // Save value of CD variable (current directory)
set ABS_PATH=%CD%
rem // Restore original directory
popd
echo Relative path: %REL_PATH%
echo Maps to path: %ABS_PATH%
Most of these answers seem crazy over complicated and super buggy, here's mine -- it works on any environment variable, no %CD%
or PUSHD
/POPD
, or for /f
nonsense -- just plain old batch functions. -- The directory & file don't even have to exist.
CALL :NORMALIZEPATH "..\..\..\foo\bar.txt"
SET BLAH=%RETVAL%
ECHO "%BLAH%"
:: ========== FUNCTIONS ==========
EXIT /B
:NORMALIZEPATH
SET RETVAL=%~f1
EXIT /B
Without having to have another batch file to pass arguments to (and use the argument operators), you can use FOR /F
:
FOR /F %%i IN ("..\relativePath") DO echo absolute path: %%~fi
where the i
in %%~fi
is the variable defined at /F %%i
. eg. if you changed that to /F %%a
then the last part would be %%~fa
.
To do the same thing right at the command prompt (and not in a batch file) replace %%
with %
...