web-dev-qa-db-ja.com

相対パスおよび/またはファイル名から絶対パスを解決します

Windowsバッチスクリプトに、ファイル名や相対パスを含む値から絶対パスを返す方法はありますか?

指定:

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

バッチファイルへの絶対パスが必要です。

例:

  • 「somefile.txt」は「C:\ Foo \」にあります
  • 「test.bat」は「C:\ Foo\Bar」にあります。
  • ユーザーが「C:\ Foo」でコマンドウィンドウを開き、Bar\test.bat ..\somefile.txtを呼び出します
  • バッチファイルでは、「C:\ Foo\somefile.txt」は%1から派生します。
143
Nathan Taylor

標準Cプログラムのように、バッチファイルでは、引数0には現在実行中のスクリプトへのパスが含まれます。 %~dp0を使用して、0番目の引数(現在のスクリプト)のパス部分のみを取得できます。このパスは常に完全修飾パスです。

%~f1を使用して最初の引数の完全修飾パスを取得することもできますが、これは現在の作業ディレクトリに応じたパスを提供しますが、これは明らかに目的のものではありません。

個人的には、バッチファイルで%~dp0%~1イディオムをよく使用します。これは、実行中のバッチのパスに関連する最初の引数を解釈します。ただし、欠点があります。最初の引数が完全に修飾されていると、惨めに失敗します。

相対および絶対パスの両方をサポートする必要がある場合は、 FrédéricMé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"
150
Adrien Plisson

今朝、同様のニーズに出くわしました。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%
138

引数を渡す(および引数演算子を使用する)別のバッチファイルがなくても、FOR /Fを使用できます。

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

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

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

35
Peter Ritchie

これは、エイドリアン・プリッソンの答えのギャップを埋めるのを助けるためです(彼がそれを編集したらすぐに支持されるべきです;-):

%〜f1を使用して、最初の引数の完全修飾パスを取得することもできますが、これは現在のパスに応じたパスを提供しますが、これは明らかに目的のものではありません。

残念ながら、私は2つを一緒に混ぜる方法がわかりません...

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

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

%~f1は、最初の引数の指定方法とは無関係に機能します:相対パスまたは絶対パス(%1を指定するときにファイルの拡張子を指定しない場合は、%~dpnx1を使用しても追加されません)。

しかし、そもそもコマンドラインでそのフルパス情報を指定しない場合、一体どのようにファイルに名前を付けますか?別のドライブ上

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

15
Kurt Pfeifle

これにはバッチ機能も使用できます。

@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
9
Axel Heider

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
6
Lycan

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

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

スクリプトの例とその出力は次のとおりです。

@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

私はこれが役立つことを願っています...それは確かに私を助けた:) P.S. DosTipsに再び感謝します!あなたが揺れます!

4
dayneo

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

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

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

1
Kristen

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

1
George Sisco

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%
0
Irq Mishell
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
0
Sergei Sachkov

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

ディレクトリ

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

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

絶対パスを返します。

D:\Projects

0
Engineer

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%

少し遅いですが、実際のスクリプト言語に頼らなければ、得られる機能を打ち負かすことは困難です。

0
stijn