상대 경로 및 / 또는 파일 이름에서 절대 경로 확인
Windows 배치 스크립트에서 파일 이름 및 / 또는 상대 경로를 포함하는 값에서 절대 경로를 반환하는 방법이 있습니까?
주어진:
"..\"
"..\somefile.txt"
배치 파일에 상대적인 절대 경로가 필요합니다.
예:
- "somefile.txt"는 "C : \ Foo \"에 있습니다.
- "test.bat"는 "C : \ Foo \ Bar"에 있습니다.
- "C : \ Foo"에서 명령 창을 열고 호출
Bar\test.bat ..\somefile.txt
- 배치 파일에서 "C : \ Foo \ somefile.txt"는
%1
표준 C 프로그램에서와 같이 배치 파일에서 인수 0에는 현재 실행중인 스크립트의 경로가 포함됩니다. %~dp0
0 번째 인수 (현재 스크립트)의 경로 부분 만 가져 오는 데 사용할 수 있습니다. 이 경로는 항상 완전한 경로입니다.
를 사용하여 첫 번째 인수의 완전한 경로를 얻을 수도 %~f1
있지만 현재 작업 디렉토리에 따라 경로를 제공합니다.
개인적으로, 나는 종종 %~dp0%~1
배치 파일에서 관용구를 사용하는데 ,이 배치는 실행 배치의 경로와 관련된 첫 번째 인수를 해석합니다. 그러나 단점이 있습니다. 첫 번째 인수가 정규화되면 비참하게 실패합니다.
상대 경로 와 절대 경로를 모두 지원해야하는 경우 Frédéric Ménez의 솔루션 을 사용할 수 있습니다 . 현재 작업 디렉토리를 임시로 변경합니다.
다음은 이러한 각 기술을 보여주는 예입니다.
@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에서 다음과 같이 실행하면
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"
배치 인수에 허용되는 수정 자 세트에 대한 설명서는 여기 ( https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/call) 에서 찾을 수 있습니다.
오늘 아침에도 비슷한 요구를 겪었습니다. 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
in %%~fi
은에 정의 된 변수 /F %%i
입니다. 예. 변경 /F %%a
한 경우 마지막 부분은입니다 %%~fa
.
(배치 파일에서가 아니라) 같은 것을 명령 프롬프트에서 권리를 위해 교체 %%
와 함께 %
...
이것은 Adrien Plisson의 답변의 격차를 메우는 데 도움이됩니다 (편집자가 그것을 수정하자마자 공감해야합니다).
% ~ f1을 사용하여 첫 번째 인수의 완전한 경로를 얻을 수도 있지만 현재 경로에 따라 경로를 제공합니다.
불행히도, 나는 2를 함께 섞는 방법을 모른다 ...
하나는 처리 할 수 %0
와 %1
마찬가지로 :
%~dpnx0
배치 파일 자체의 완전한 drive + path + name + extension의 경우
%~f0
에도 충분합니다.%~dpnx1
완전한 인수 인 첫 번째 인자의 drive + path + name + extension (그것이 파일 이름이라면)
%~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
I have not seen many solutions to this problem. Some solutions make use of directory traversal using CD and others make use of batch functions. My personal preference has been for batch functions and in particular, the MakeAbsolute function as provided by DosTips.
The function has some real benefits, primarily that it does not change your current working directory and secondly that the paths being evaluated don't even have to exist. You can find some helpful tips on how to use the function here too.
Here is an example script and its outputs:
@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
And the output:
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
I hope this helps... It sure helped me :) P.S. Thanks again to DosTips! You rock!
In your example, from Bar\test.bat, DIR /B /S ..\somefile.txt would return the full path.
You can just concatenate them.
SET ABS_PATH=%~dp0
SET REL_PATH=..\SomeFile.txt
SET COMBINED_PATH=%ABS_PATH%%REL_PATH%
it looks odd with \..\ in the middle of your path but it works. No need to do anything crazy :)
PowerShell is pretty common these days so I use it often as a quick way to invoke C# since that has functions for pretty much everything:
@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%
It's a bit slow, but the functionality gained is hard to beat unless without resorting to an actual scripting language.
stijn's solution works with subfolders under 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%
Files See all other answers
Directories
With ..
being your relative path, and assuming you are currently in D:\Projects\EditorProject
:
cd .. & cd & cd EditorProject
(the relative path)
returns absolute path e.g.
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
'Programing' 카테고리의 다른 글
여러 줄에서 ghci로 함수를 정의하는 방법은 무엇입니까? (0) | 2020.06.14 |
---|---|
두 개의 인라인 블록, 너비 50 % 요소가 두 번째 줄로 줄 바꿈 (0) | 2020.06.14 |
Base64 Java 문자열 인코딩 및 디코딩 (0) | 2020.06.14 |
일반적인 CSS 미디어 쿼리 중단 점 (0) | 2020.06.14 |
공분산 및 공분산 실제 사례 (0) | 2020.06.14 |