문제

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

배치 인수에 허용되는 수정 자 세트에 대한 문서는 다음과 같습니다.https://docs.microsoft.com/en-us/windows-eserver/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 안에 %%~fi 변수가 정의되어 있습니다 /F %%i. 예를 들어. 당신이 그것을 변경했다면 /F %%a 그러면 마지막 부분이 될 것입니다 %%~fa.

명령 프롬프트 (배치 파일이 아닌)에서 동일한 작업을 바로 수행하려면 교체 %% ~와 함께 %...

이는 Adrien Plisson의 답변에서 공백을 메우는 데 도움이 됩니다(편집하자마자 찬성해야 합니다 ;-).

%~f1을 사용하여 첫 번째 인수의 정규화된 경로를 얻을 수도 있지만 이는 현재 경로에 따라 경로를 제공하는데 이는 분명히 원하는 것이 아닙니다.

아쉽게도 이 둘을 어떻게 섞어야할지 모르겠네요...

하나는 처리 할 수 ​​​​있습니다 %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에게 다시 한 번 감사드립니다! 당신은 바위!

예에서, bar 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%

약간 느리지 만 실제 스크립팅 언어에 의지하지 않으면 얻은 기능은 이길 수 없습니다.

Stijn의 솔루션은 하위 폴더와 함께 작동합니다 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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top