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
배치 파일 자체의 완전한 드라이브 + 경로 + 이름 + 확장
%~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