172

Is there a way in a Windows batch script to return an absolute path from a value containing a filename and/or relative path?

Given:

"..\"
"..\somefile.txt"

I need the absolute path relative to the batch file.

Example:

  • "somefile.txt" is located in "C:\Foo\"
  • "test.bat" is located in "C:\Foo\Bar".
  • User opens a command window in "C:\Foo" and calls Bar\test.bat ..\somefile.txt
  • In the batch file "C:\Foo\somefile.txt" would be derived from %1
4

14 に答える 14

173

バッチ ファイルでは、標準の 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 にあります。

于 2009-10-29T19:25:33.803 に答える
162

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%
于 2010-12-20T10:26:10.843 に答える
38

引数を渡す (および引数演算子を使用する) 別のバッチ ファイルを用意する必要なく、次のように使用できますFOR /F

FOR /F %%i IN ("..\relativePath") DO echo absolute path: %%~fi

ここで、iin%%~fiは で定義された変数です/F %%i。例えば。それを に変更すると/F %%a、最後の部分は になります%%~fa

コマンドプロンプトで(バッチファイルではなく)同じことを行うには、%%...%に置き換えます

于 2012-04-04T20:46:37.813 に答える
15

これは、エイドリアン・プリソンの回答のギャップを埋めるのに役立ちます(編集したらすぐに賛成する必要があります;-):

%~f1 を使用して最初の引数の完全修飾パスを取得することもできますが、これは現在のパスに従ってパスを提供しますが、これは明らかに必要なものではありません。

残念ながら、2つを組み合わせる方法がわかりません...

同様%0に処理できます:%1

  • %~dpnx0バッチファイル自体の完全修飾ドライブ+パス+名前+拡張子の場合
    %~f0も十分です。
  • %~dpnx1最初の引数の完全修飾ドライブ+パス+名前+拡張子[それがファイル名である場合]
    %~f1でも十分です。

%~f1最初の引数をどのように指定したかに関係なく動作します: 相対パスまたは絶対パス (名前%1を付けるときにファイルの拡張子を指定しない場合、 -- を使用しても追加されません%~dpnx1。ただし.

しかし、そもそもコマンドラインでそのフルパス情報を提供しない場合、別のドライブ上のファイルに名前を付けるにはどうすればよいでしょうか?

ただし、パス (ドライブ文字なし)、ファイル名 (拡張子なし)、拡張子付きの完全なファイル名、またはファイル名の拡張子のみに関心がある場合は、 %~p0%~n0%~nx0およびが便利な場合があります。%~x0ただし、 while%~p1%~n1最初の引数のパスまたは名前を見つけるために機能し、コマンドラインで既に使用していない限り、拡張子を追加して表示しないことに%~nx1注意してください。%~x1

于 2010-08-13T20:33:11.680 に答える
12

これにはバッチ関数も使用できます。

@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
于 2011-07-06T10:51:38.440 に答える
5

この問題の解決策はあまり見たことがありません。CD を使用したディレクトリ トラバーサルを利用するソリューションもあれば、バッチ機能を利用するソリューションもあります。私の個人的な好みは、バッチ関数であり、特にDosTipsによって提供されるMakeAbsolute関数です。

この関数には、いくつかの実際の利点があります。主に、現在の作業ディレクトリが変更されないことと、評価されるパスが存在する必要がないことです。ここでも、関数の使用方法に関する役立つヒントを見つけることができます。

スクリプトの例とその出力を次に示します。

@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に再び感謝します! あなたはロックします!

于 2012-02-03T13:53:14.553 に答える
2

それらを連結するだけです。

SET ABS_PATH=%~dp0 
SET REL_PATH=..\SomeFile.txt
SET COMBINED_PATH=%ABS_PATH%%REL_PATH%

パスの途中に \..\ があると奇妙に見えますが、機能します。クレイジーなことをする必要はありません:)

于 2012-11-28T00:28:15.147 に答える
1

あなたの例では、Bar\test.bat から、DIR /B /S ..\somefile.txt は完全なパスを返します。

于 2009-10-29T19:17:09.307 に答える
0

最近では PowerShell が非常に一般的になっているため、C# を呼び出すための簡単な方法としてよく使用します。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%

少し遅いですが、実際のスクリプト言語に頼らない限り、得られる機能に勝るものはありません。

于 2013-07-07T10:35:15.383 に答える
0

ファイル他のすべての回答を見る

ディレクトリ

あなた..の相対パスであり、あなたが現在いると仮定するとD:\Projects\EditorProject

cd .. & cd & cd EditorProject(相対パス)

絶対パスを返します。

D:\Projects

于 2015-08-03T08:49:20.817 に答える
0
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
于 2015-09-24T15:43:14.520 に答える