从相对path和/或文件名parsing绝对path

有没有办法在Windows批处理脚本从包含文件名和/或相对path的值返回绝对path?

鉴于:

"..\" "..\somefile.txt" 

我需要相对于batch file的绝对path。

例:

  • “somefile.txt”位于“C:\ Foo \”
  • “test.bat”位于“C:\ Foo \ Bar”中。
  • 用户在“C:\ Foo”中打开命令窗口并调用Bar\test.bat ..\somefile.txt
  • 在batch file“C:\ Foo \ somefile.txt”将从%1派生

在batch file中,如在标准C程序中一样,参数0包含当前正在执行的脚本的path。 您可以使用%~dp0来仅获取第0个参数(即当前脚本)的path部分 – 此path始终是完全限定的path。

你也可以通过使用%~f1来得到第一个参数的全限定path,但是这会给出一个根据当前工作目录的path,这显然不是你想要的。

就我个人而言,我经常在我的batch file中使用%~dp0%~1习语,它解释了相对于执行批处理path的第一个参数。 但是它有一个缺点:如果第一个参数是完全合格的,它就会失败。

如果您需要支持相对path绝对path,则可以使用FrédéricMénez的解决scheme :临时更改当前工作目录。

下面是一个将演示这些技术的例子:

 @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 

如果将其保存为c:\ temp \ example.bat,并从c:\ Users \ Public as运行

c:\ Users \ Public> \ temp \ example.bat .. \ windows

你会看到下面的输出:

 %~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" 

今天早上我遇到了类似的需求:如何在Windows命令脚本中将相对path转换为绝对path。

以下是诀窍:

 @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% 

大多数这些答案似乎是疯狂的复杂和超级越野车,这是我的 – 它适用于任何环境variables,没有%CD%PUSHD / POPD ,或for /f废话 – 只是普通的旧批处理function。 – 目录&文件甚至不必存在。

 CALL :NORMALIZEPATH "..\..\..\foo\bar.txt" SET BLAH=%RETVAL% ECHO "%BLAH%" :: ========== FUNCTIONS ========== EXIT /B :NORMALIZEPATH SET RETVAL=%~dpfn1 EXIT /B 

不必有另一个batch file传递参数(并使用参数运算符),您可以使用FOR /F

 FOR /F %%i IN ("..\relativePath") DO echo absolute path: %%~fi 

其中%%~fi中的i是在/F %%i处定义的variables。 例如。 如果您将其更改为/F %%a那么最后一部分将是%%~fa

要在命令提示符处(而不是在batch file中)执行相同的操作,请将%%replace为%

这是为了帮助填补Adrien Plisson的答案(在他编辑它时应立即提出); – ):

你也可以通过使用%〜f1来得到你的第一个参数的全限定path,但是这给出了一个根据当前path的path,这显然不是你想要的。

不幸的是,我不知道如何混合在一起…

可以同样处理%0%1

  • %~dpnx0为完全合格的驱动器+path+名称+batch file本身的扩展名,
    %~f0也足够了;
  • %~dpnx1完全合格的驱动器+path+名称+扩展名的第一个参数[如果这是一个文件名],
    %~f1也足够了;

%~f1将独立于指定第一个参数的方式工作:使用相对path或使用绝对path(如果在命名%1时未指定文件扩展名,则不会添加,即使使用%~dpnx1 – 但是。

但是如果你不在命令行上提供完整的path信息,那么如何在不同的驱动器上命名一个文件呢?

但是,如果你对path(没有驱动器号),文件名(没有扩展名)感兴趣,只有扩展名或文件名扩展名的完整文件名, %~nx0%~nx0%~nx0%~x0 %~nx0可能会派上用场。 但是请注意, %~p1%~n1将查找第一个参数的path或名称, %~nx1%~x1将不会添加+显示扩展名,除非已经在命令行上使用它。

您也可以使用批处理function:

 @echo off setlocal goto MAIN ::----------------------------------------------- :: "%~f2" get abs path of %~2. ::"%~fs2" get abs path with short names of %~2. :setAbsPath setlocal set __absPath=%~f2 endlocal && set %1=%__absPath% goto :eof ::----------------------------------------------- :MAIN call :setAbsPath ABS_PATH ..\ echo %ABS_PATH% endlocal 

我还没有看到这个问题的很多解决scheme。 一些解决scheme使用CD的目录遍历,而其他的使用批处理function。 我的个人喜好是批处理function,特别是由DosTips提供的MakeAbsolutefunction。

这个函数有一些真正的好处,主要是它不会改变你当前的工作目录,其次是被评估的path甚至不需要存在。 你也可以在这里find一些关于如何使用这个函数的有用提示。

这是一个脚本及其输出示例:

 @echo off set scriptpath=%~dp0 set siblingfile=sibling.bat set siblingfolder=sibling\ set fnwsfolder=folder name with spaces\ set descendantfolder=sibling\descendant\ set ancestorfolder=..\..\ set cousinfolder=..\uncle\cousin call:MakeAbsolute siblingfile "%scriptpath%" call:MakeAbsolute siblingfolder "%scriptpath%" call:MakeAbsolute fnwsfolder "%scriptpath%" call:MakeAbsolute descendantfolder "%scriptpath%" call:MakeAbsolute ancestorfolder "%scriptpath%" call:MakeAbsolute cousinfolder "%scriptpath%" echo scriptpath: %scriptpath% echo siblingfile: %siblingfile% echo siblingfolder: %siblingfolder% echo fnwsfolder: %fnwsfolder% echo descendantfolder: %descendantfolder% echo ancestorfolder: %ancestorfolder% echo cousinfolder: %cousinfolder% GOTO:EOF ::---------------------------------------------------------------------------------- :: Function declarations :: Handy to read http://www.dostips.com/DtTutoFunctions.php for how dos functions :: work. ::---------------------------------------------------------------------------------- :MakeAbsolute file base -- makes a file name absolute considering a base path :: -- file [in,out] - variable with file name to be converted, or file name itself for result in stdout :: -- base [in,opt] - base path, leave blank for current directory :$created 20060101 :$changed 20080219 :$categories Path :$source http://www.dostips.com SETLOCAL ENABLEDELAYEDEXPANSION set "src=%~1" if defined %1 set "src=!%~1!" set "bas=%~2" if not defined bas set "bas=%cd%" for /f "tokens=*" %%a in ("%bas%.\%src%") do set "src=%%~fa" ( ENDLOCAL & REM RETURN VALUES IF defined %1 (SET %~1=%src%) ELSE ECHO.%src% ) EXIT /b 

而输出:

 C:\Users\dayneo\Documents>myscript scriptpath: C:\Users\dayneo\Documents\ siblingfile: C:\Users\dayneo\Documents\sibling.bat siblingfolder: C:\Users\dayneo\Documents\sibling\ fnwsfolder: C:\Users\dayneo\Documents\folder name with spaces\ descendantfolder: C:\Users\dayneo\Documents\sibling\descendant\ ancestorfolder: C:\Users\ cousinfolder: C:\Users\dayneo\uncle\cousin 

我希望这有助于…它肯定帮了我:) PS再次感谢DosTips! 你摇滚!

BrainSlugs83的优秀解决scheme略有改进。 通用来允许在调用中命名输出环境variables。

 @echo off setlocal EnableDelayedExpansion rem Example input value. set RelativePath=doc\build rem Resolve path. call :ResolvePath AbsolutePath %RelativePath% rem Output result. echo %AbsolutePath% rem End. exit /b rem === Functions === rem Resolve path to absolute. rem Param 1: Name of output variable. rem Param 2: Path to resolve. rem Return: Resolved absolute path. :ResolvePath set %1=%~dpfn2 exit /b 

如果从C:\project输出运行是:

 C:\project\doc\build 

在你的例子中,从Bar \ test.bat,DIR / B / S .. \ somefile.txt将返回完整的path。

你可以连接它们。

 SET ABS_PATH=%~dp0 SET REL_PATH=..\SomeFile.txt SET COMBINED_PATH=%ABS_PATH%%REL_PATH% 

它在你的path中间看起来很奇怪\ \ \但它的工作原理。 不需要做任何疯狂的事情:)

PowerShell现在很常见,所以我经常使用它作为调用C#的快捷方式,因为它具有几乎所有的function:

 @echo off set pathToResolve=%~dp0\..\SomeFile.txt for /f "delims=" %%a in ('powershell -Command "[System.IO.Path]::GetFullPath( '%projectDirMc%' )"') do @set resolvedPath=%%a echo Resolved path: %resolvedPath% 

这有点慢,但所获得的function是很难打败的,除非不诉诸于实际的脚本语言。

stijn的解决scheme在C:\Program Files (86)\下的子文件夹下工作,

 @echo off set projectDirMc=test.txt for /f "delims=" %%a in ('powershell -Command "[System.IO.Path]::GetFullPath( '%projectDirMc%' )"') do @set resolvedPath=%%a echo full path: %resolvedPath% 

文件查看所有其他答案

目录

..作为你的相对path,假设你目前在D:\Projects\EditorProject

cd .. & cd & cd EditorProject (相对path)

返回绝对path例如

D:\Projects

 SET CD=%~DP0 SET REL_PATH=%CD%..\..\build\ call :ABSOLUTE_PATH ABS_PATH %REL_PATH% ECHO %REL_PATH% ECHO %ABS_PATH% pause exit /b :ABSOLUTE_PATH SET %1=%~f2 exit /b