相対パスおよび/またはファイル名から絶対パスを解決します
-
22-07-2019 - |
質問
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é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"
バッチ引数で許可される修飾子セットのドキュメントは、次の場所にあります。 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
%%〜fi
の i
は、 / F %% i
で定義された変数です。例えば。これを / F %% a
に変更すると、最後の部分は %%〜fa
になります。
コマンドプロンプトで(バッチファイルではなく)同じことを行うには、 %%
を%
に置き換えます...
これは、エイドリアン・プリッソンの答えのギャップを埋めるのを助けるためです(彼がそれを編集したらすぐに賛成すべきです;-):
%〜f1を使用して、最初の引数の完全修飾パスを取得することもできますが、これは現在のパスに応じたパスを提供します。これは明らかに目的のものではありません。
残念ながら、2つを混ぜる方法がわかりません...
同様に%0
および%1
を処理できます:
-
%〜dpnx0
完全修飾ドライブ+パス+名前+バッチファイル自体の拡張子、
%〜f0
でも十分です; -
%〜dpnx1
完全修飾ドライブ+パス+名前+最初の引数の拡張子(それがファイル名である場合)、
%〜f1
でも十分です;
%〜f1
は、最初の引数の指定方法に関係なく機能します:相対パスまたは絶対パス(%1 <の命名時にファイルの拡張子を指定しない場合/ code>、
%〜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
これが役立つことを願っています...確かに私を助けた:) 追伸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 ..&amp; cd&amp; 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