[windows] 상대 경로 및 / 또는 파일 이름에서 절대 경로 확인

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에는 현재 실행중인 스크립트의 경로가 포함됩니다. %~dp00 번째 인수 (현재 스크립트)의 경로 부분 만 가져 오는 데 사용할 수 있습니다. 이 경로는 항상 완전한 경로입니다.

를 사용하여 첫 번째 인수의 완전한 경로를 얻을 수도 %~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

여기서 iin %%~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