有没有在Windows批处理脚本的方式来从包含文件名和/或相对路径返回一个值的绝对路径?
鉴于:
"..\"
"..\somefile.txt"
我需要绝对相对于该批处理文件的路径。
例:
- “somefile.txt” 位于 “C:\富\”
- “test.bat的” 位于 “C:\富\酒吧”。
- 用户打开一个命令行窗口中的“C:\富”,并呼吁
Bar\test.bat ..\somefile.txt
- 在批处理文件“C:\富\ somefile.txt”将衍生自
%1
有没有在Windows批处理脚本的方式来从包含文件名和/或相对路径返回一个值的绝对路径?
鉴于:
"..\"
"..\somefile.txt"
我需要绝对相对于该批处理文件的路径。
例:
Bar\test.bat ..\somefile.txt
%1
在批处理文件,如标准的C程序,参数0包含路径到当前执行脚本。 您可以使用%~dp0
只得到第0参数的路径部分(这是当前脚本) -这条道路始终是一个完全合格的路径。
您也可以通过让你的第一个参数的完全合格的路径%~f1
,但根据当前的工作目录,这显然不是你想要的这个给出了一个路径。
就个人而言,我经常使用%~dp0%~1
成语在我的批处理文件,该文件第一部分相对于执行批处理的路径参数解释。 它有一个缺点是:如果第一个参数是完全合格它悲惨的失败了。
如果你需要同时支持相对和绝对路径,你可以利用的弗雷德里克·梅内斯的解决方案 :临时改变当前的工作目录。
这里是一个将展示各自这些技术的一个例子:
@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运行:\用户\公用如
C:\用户\公用> \ 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命令脚本中的绝对路径。
下面的伎俩:
@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%
大多数这些问题的答案似乎过于复杂和超级越野车疯了,这里是我的-它适用于任何环境变量,无需%CD%
或PUSHD
/ POPD
,或for /f
废话-只是普通的老批号等功能。 - 目录和文件甚至不必存在。
CALL :NORMALIZEPATH "..\..\..\foo\bar.txt"
SET BLAH=%RETVAL%
ECHO "%BLAH%"
:: ========== FUNCTIONS ==========
EXIT /B
:NORMALIZEPATH
SET RETVAL=%~dpfn1
EXIT /B
而不必有另一个批处理文件将参数传递给(和使用参数运营商),您可以用FOR /F
:
FOR /F %%i IN ("..\relativePath") DO echo absolute path: %%~fi
其中i
在%%~fi
是在定义的变量/F %%i
。 例如。 如果你改变了对/F %%a
则最后部分将%%~fa
。
要做到同样的事情就在命令提示符(而不是在一个批处理文件)替换%%
用%
...
这是为了帮助填补了阿德里安Plisson的答案(应该只要他编辑它;-) upvoted的差距:
您还可以通过使用%〜F1得到你的第一个参数的完全合格的路径,但根据目前的路径,这显然不是你想要的这个给出了一个路径。
不幸的是,我不知道如何将2混合在一起...
一个可以处理%0
和%1
同样:
%~dpnx0
的批处理文件本身的完全合格的驱动器+路径+名称+扩展, %~f0
也足够了; %~dpnx1
为完全合格的驱动器+路径+姓名+第一个参数的扩展[如果这是一个文件名都] %~f1
也足够了; %~f1
将独立工作,你是如何做到指定的第一个参数:相对路径或绝对路径(如果不指定文件的扩展名,当命名%1
,它不会被添加,即使您使用%~dpnx1
- 但是。
但是,如何在地球上,你会说出不同的驱动器上的文件无论如何,如果你不给就摆在首位的命令行是完整路径信息?
然而, %~p0
, %~n0
, %~nx0
和%~x0
可以派上用场了,你应该关心路径(无驱动器号),文件名(不含扩展名),文件全名以扩展或只有文件扩展名。 但要注意,虽然%~p1
和%~n1
将努力找出第一个参数的路径或名称, %~nx1
和%~x1
不会增加+显示扩展名,除非你使用它的命令行了。
您也可以使用批处理功能如下:
@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
小改进BrainSlugs83的优秀的解决方案 。 广义允许在呼叫命名输出环境变量。
@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
我还没有看到这个问题的许多解决方案。 一些解决方案使用CD利用目录遍历和他人利用批处理功能。 我个人的偏好已经批量功能,尤其是MakeAbsolute功能的由DosTips提供。
该函数有一些实实在在的好处,主要是它不改变当前的工作目录,其次是被评估的路径,甚至不必存在。 你可以找到关于如何使用该功能的一些有用的技巧在这里了。
下面是一个例子脚本及其输出:
@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! 你摇滚!
在你的榜样,从酒吧\ test.bat的,DIR / B / S .. \ somefile.txt将返回完整路径。
您只需将它们连接起来。
SET ABS_PATH=%~dp0
SET REL_PATH=..\SomeFile.txt
SET COMBINED_PATH=%ABS_PATH%%REL_PATH%
它看起来很奇怪与\ .. \在路中间,但它的工作原理。 无需做任何疯狂的:)
PowerShell是这些天很常见的,所以我用它经常作为一个快速的方式来调用C#,因为这对几乎所有的功能:
@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%
这是一个有点慢,但获得的功能是很难被击败,除非不诉诸到实际的脚本语言。
斯泰恩的解决方案包括子文件夹下的作品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%
文件显示所有其他的答案
目录
随着..
是你的相对路径,并假设您目前在D:\Projects\EditorProject
:
cd .. & cd & cd EditorProject
(相对路径)
返回绝对路径如
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