Programing

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

lottogame 2020. 6. 14. 10:22
반응형

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


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배치 파일 자체의 완전한 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

참고URL : https://stackoverflow.com/questions/1645843/resolve-absolute-path-from-relative-path-and-or-file-name

반응형