BATファイルで `%〜dp0`を展開した後、予期しない重複したディレクトリ名


7

Windows 10 Enterprise x64を使用しています。次のディレクトリ階層があり、BATファイルが最も内側のレベルにあります。

C:\
  dir\
    my files\
      run.bat

BATファイルには次の行が含まれています。

@pushd %~dp0
@echo %~dp0
@popd

(の意味と使用法は%~dp0、ヘルプトピックfor /?この回答で説明されています)

現在のディレクトリがであるコマンドプロンプトからBATファイルを実行するとC:\dir\my files、非常に妥当な結果が得られます。

C:\dir\my files>run.bat
C:\dir\my files\

しかし、親ディレクトリから呼び出すとC:\dir、次のようになります:

C:\dir>"my files"\run.bat
C:\dir\my files\my files"\

え?最も内側のディレクトリ名が重複している"\ため、最後にいくつかの迷子の文字があることに注意してください。別の方法で試してみましょう:

C:\dir>"my files\run.bat"
C:\dir\my files\my files\

浮遊文字はなくなりましたが、ディレクトリ名はまだ複製されています。これの説明は何ですか?どのディレクトリから呼び出されても同じ出力が得られるようにBATファイルを変更するにはどうすればよいですか?

もちろん、私の実際のシナリオは、この単純化されたバージョンよりも複雑です。の値%~dp0は、他の文字列と連結され、環境変数に割り当てられ、他のスクリプトに引数として渡されます。


ファイルの名前を.cmdに変更して、何か変更がないか確認してください。
キリルオセンコフ

@KirillOsenkov変更なし
ウラジミールレシェトニコフ

合理的な回避策を見つけました。%cd%新しい現在のディレクトリをプッシュした後、代わりに変数を使用しますが、以前はなぜ機能しなかったのかまだわかりません。
ウラジミールレシェトニコフ

このようにしてみてください.\"my files"\run.bat
Nicke Manarin

2
@NickeManarinユーザーがBATファイルを呼び出す方法を制御できません。私はそのコンテンツを管理するだけです。
ウラジミールレシェトニコフ

回答:


4

これは、cmd.exeの内の既知のバグ/デザイン欠乏 - %~dp0とバッチスクリプトへのパスが引用された場合の変異体は、間違った結果を与えることができます。

回避策があります。あなたは確実に呼び出されたサブルーチン内から値を取得することができます(のような少なくとも一つの修飾ことに注意してください~d~fあなたがサブルーチンを得る他に、などを使用する必要があります:label

@echo off
setlocal
pushd %~dp0
echo From main fails: "%~dp0"
call :test
popd
exit /b

:test
echo From subroutine OK: "%~dp0"

-サンプル出力-

d:\dir>"my files\test.bat"
From main fails: "d:\dir\my files\my files\"
From subroutine OK: "d:\dir\my files\"

1

回避策として、ディレクトリを事前に保存します。

set "dir=%~dp0"

これは%0argvarg 0のように)実際に呼び出されたパスであるため、例ではまたはのいずれ"my files"\run.bat"my files\run.bat"です。

すると%~dp0、cmd.exeは現在のディレクトリからの相対パスを構築し、要求した部分を抽出します。

pushd、「フルパス」(%~f0)は次のいずれかになります。

C:\dir\my files\my files\run.bat
C:\dir\my files\my files"\run.bat

...次に、ファイル名を削除して結果を取得します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.