5

次の %~d0 がバッチ ファイルのドライブ文字 S: を返すのに失敗するのはなぜですか?

S:\!DJ DAP>type test.bat
R:
%~d0

S:\!DJ DAP>call test.bat

S:\!DJ DAP>R:

R:\>S:

S:\!DJ DAP>call "test.bat"

S:\!DJ DAP>R:

R:\>R:

R:\>

Jerry と MC からの次の応答を編集します。同じことを示す CALL 以外の例を次に示します。

R:\>s:

S:\!DJ DAP>type test.bat
R:
%~d0

S:\!DJ DAP>test.bat

S:\!DJ DAP>R:

R:\>S:

S:\!DJ DAP>"test.bat"

S:\!DJ DAP>R:

R:\>R:

R:\>
4

4 に答える 4

7

編集 - npocmaka、あなたは正しいです。変。

元の回答が削除されました - 私は間違っていました。

しかし、問題はcallコマンドではありません。問題は引用符とcmdです。

テスト後、ファイル名がどのように処理され、cmd が API 呼び出しでいくつかのエラーをどのように処理するかについて、バグ/機能のように見えます。

次のバッチ ファイル (test.cmd) を使用

@echo off
    setlocal enableextensions

    echo Calling subroutine from drive d:
    call :getInfo
    echo.

    c:
    echo Calling subroutine from drive c:
    call :getInfo
    echo.

    echo Getting data directly without subroutine

:getInfo
    echo ---------------------------------------------------------
    echo cd    : %cd%
    echo d0    : %~d0
    echo dp0   : %~dp0
    echo f0    : %~f0
    echo ---------------------------------------------------------
    echo.
    goto :EOF

d:\temp\testCMD に配置され、ドライブ c: の現在のディレクトリは C:\Users です。実行結果は次のとおりです。

1.- cmd ディレクトリから引用符なしで呼び出す:test.cmd

Calling subroutine from drive d:
---------------------------------------------------------
cd    : D:\temp\testCMD
d0    : D:
dp0   : D:\temp\testCMD\
f0    : D:\temp\testCMD\test.cmd
---------------------------------------------------------


Calling subroutine from drive c:
---------------------------------------------------------
cd    : C:\Users
d0    : D:
dp0   : D:\temp\testCMD\
f0    : D:\temp\testCMD\test.cmd
---------------------------------------------------------


Getting data directly without subroutine
---------------------------------------------------------
cd    : C:\Users
d0    : D:
dp0   : D:\temp\testCMD\
f0    : D:\temp\testCMD\test.cmd
---------------------------------------------------------

結果:すべてOK。

2.- cmd ディレクトリから引用符で呼び出す"test.cmd"(いいえ、callコマンドは必要ありません)

Calling subroutine from drive d:
---------------------------------------------------------
cd    : D:\temp\testCMD
d0    : D:
dp0   : D:\temp\testCMD\
f0    : D:\temp\testCMD\test.cmd
---------------------------------------------------------


Calling subroutine from drive c:
---------------------------------------------------------
cd    : C:\Users
d0    : D:
dp0   : D:\temp\testCMD\
f0    : D:\temp\testCMD\test.cmd
---------------------------------------------------------


Getting data directly without subroutine
---------------------------------------------------------
cd    : C:\Users
d0    : C:
dp0   : C:\Users\
f0    : C:\Users\test.cmd
---------------------------------------------------------

結果: cmd のメイン実行行から直接取得した場合にのみ、%~d0 の正しい値を取得できません。サブルーチン呼び出しと同じことが期待どおりに機能します。

引用符なしでテストされたすべてのシナリオは、失敗することなく機能します。引用符を使用して、呼び出し行にドライブ (ej: "d:.\test.cmd") が含まれている場合、すべての値が正しく取得されます。ドライブがバッチ コールに含まれていない場合 (ej:"test.cmd"パスにバッチ ディレクトリがある場合、または"\temp\testCMD\test.cmd"D: のルートから)、誤った値が取得されますが、バッチ ファイルの実行のメイン行からのみ取得されます。サブルーチンは常に正しい値を取得します。

なんで?わかりません。しかし、procmon を使用して cmd の実行をトレースする場合、失敗した場合、cmd.exe がファイルの情報を取得しようとすると、QueryDirectory API 呼び出しが行われ、応答C:\Users\test.cmdが返されますが、cmd はそれを無視して実行を継続し、間違った値を表示しますNO SUCH FILE

では、無回答です、すみません。しかし、私はこれを「文書化」しなければなりませんでした。部屋に教祖?

更新:詳細はこちら

于 2013-11-05T07:19:38.413 に答える
5

dbenham のように: 魅力的です!

cmd.exeの機能だと思います。

引用符は%0、メインのバッチ コンテキストから削除されません。
しかし、それらはすべてサブルーチンの呼び出しによって取り除かれます。これは、2 つ以上の引用符が使用されている場合に実現できます%0

ParamTest.bat

@echo off
cls
setlocal
d:
echo Main %%0: %~0, %~f0
echo Main %%1: %~1, %~f1
call :func %1
exit /b

:func
echo Func %%0: %~0, %~f0
echo Func %%1: %~1, %~f1
exit /b

出力:""""PARAM"test.BAT" ""paramTEST.bAt""

メイン %0: """PARAM"test.BAT, D:\"""PARAM"test.BAT
メイン %1: "paramTEST.bAt", D:\"paramTEST.bAt"
関数 %0: :func、C:\temp\ParamTest.bat
Func %1: "paramTEST.bAt", D:\"paramTEST.bAt"

また、コンテンツが同じように見える場合でも、異なる結果が得られるため、関連するディレクトリ%0保存しているようです。 しかし、おそらくパスの前に.%~f0%~f1
%0

出力:PARAMtest.BAT paramTEST.bAt

メイン %0: PARAMtest.BAT、C:\temp\ParamTest.bat
メイン %1: paramTEST.bAt、D:\paramTEST.bAt
関数 %0: :func、C:\temp\ParamTest.bat
関数 %1: paramTEST.bAt、D:\paramTEST.bAt
于 2013-11-05T19:45:44.203 に答える
1

"%~dpi"ファイルを一覧表示しているが、作業ディレクトリが別のフォルダーまたはドライブである場合にも失敗します。ファイルのパスではなく、作業ディレクトリが表示されます。

%~d0ここでの解決策は、ドライブを変更する前に取得することだと思います。

于 2013-11-05T12:29:06.217 に答える