web-dev-qa-db-ja.com

batファイルにパラメーターとしてスペースを含むパスを渡す

既知のディレクトリからユーザーが指定したディレクトリにファイルをコピーする単純なバットスクリプトがあります。スクリプトにパス(スペースが含まれている場合があります)を渡してxcopyコマンドで使用するにはどうすればよいですか?


私のコードには次のものがあります

:READ_PWA_PATH
    if "%1" == "" ( 
        rem Set default path
        set PWA_PATH="C:\Program Files\PWA"
        rem
        echo You have not specified your PWA url.
        echo Default will be assumed: C:\Program Files\PWA. 
        choice /C:YN /M:"Do you wish to continue [Y] or cancel the script [N]?"
            IF ERRORLEVEL ==2 GOTO CANCEL
            IF ERRORLEVEL ==1 GOTO READ_WSS_SERVER_EXTENSIONS_PATH
        GOTO END
    ) else (
        set PWA_PATH=%1
    )

単にスクリプトを呼び出すと、次のエラーが表示されます。

C:\Projects\Setup>install.cmd "C:\program files (x86)"

-----------------
SETUP SCRIPT
-----------------

files was unexpected at this time.
C:\Projects\Setup>
58
kjv

興味深いもの。 cmd/commandでの引用​​符の処理に関する引用符の収集が大好きです。

特定のスクリプトは、「%1」の代わりに%1を使用して修正されます!!!

「エコーオン」を追加する(またはエコーオフを取り除く)ことで、簡単にそれを見つけることができます。

21
vrdhn

つかいます "%~1"%~1単独で周囲の引用符を削除します。ただし、入力パラメータ%1に引用符があるかどうかは、"%~1"確実に追加されること。これは、変数を連結するときに特に役立ちます。 convert.exe "%~1.input" "%~1.output"

102
zikaS

「%〜1」はほとんどの場合機能します。ただし、このために注意しなければならないことがいくつかあります。

  1. Windows NT 4.0ではサポートされていません。 Windows 2000以降が必要です。 (古いOSと互換性のあるスクリプトをコーディングしている場合は、注意してください。)
  2. パラメータを安全かつサニタイズしません。私の観察では、CMDスクリプトのコマンドライン引数を適切にサニタイズする方法はありません。

2番目のポイントを示すために、例を挙げましょう。

REM example.cmd
ECHO %~1

example.cmd dummy^&DIRで実行します。アンパーサンドはここでエスケープされ(^&)、シェルがコマンド区切り文字として解釈されないようにし、スクリプトに渡される引数の一部になります。 DIRはコマンドとして解釈されますスクリプトを実行しているサブシェルの内部

それを引用することはしばらくは働くかもしれないが、それでも安全ではない

REM example2.cmd
SETLOCAL EnableExtensions EnableDelayedExpansion
SET "arg1=%~1"
ECHO "%~1"
ECHO !arg1:"=!

example2.cmd foo^"^&DIR^&^"barはそれを壊します。 DIRコマンドは、SETの直後と最初のECHOの直後の2回実行されます。引用符で囲まれていると思われる"%~1"は、引数自体によって引用符で囲まれていないことがわかります。

そのため、解析引数を安全にする方法はありません。

(編集:EnableDelayedExpansionはWindows NT 4でも機能しません。ここの情報のおかげで: http://www.robvanderwoude.com/local.php

6
Explorer09

パスにスペースが含まれている場合は、引用符( ")で囲む必要があります。

それがまさにあなたが求めているものかどうかはわかりませんか?

5
user7094
@echo off
setlocal enableextensions enabledelayedexpansion

if %1=="" (     
        rem Set default path
        set PWA_PATH="C:\Program Files\PWA"
        rem
        echo You have not specified your PWA url.
        echo Default will be assumed: C:\Program Files\PWA.     
        choice /C:YN /M:"Do you wish to continue [Y] or cancel the script [N]?"
                IF ERRORLEVEL ==2 GOTO CANCEL
                IF ERRORLEVEL ==1 GOTO READ_WSS_SERVER_EXTENSIONS_PATH
        GOTO END
    ) else (
        set PWA_PATH=%1
        @echo !PWA_PATH! vs. %1
        goto end
    )
:READ_WSS_SERVER_EXTENSIONS_PATH
echo ok
goto end
:CANCEL
echo cancelled
:end
echo. final %PWA_PATH% vs. %1

VardhanDotNet が言及しているように、%1で十分です。

"%1%"は、引用符を囲む引用符を追加します:""c:\Program Files\xxx""

  • '空の文字列'("")、
  • 続けて「c:\ Program」、
  • 「予期しないここ」「Files\xxx」が続く、
  • その後に空の文字列が続きます(""

ただし、IF句内でPWA_PATHを使用する必要がある場合は、!PWA_PATH!として参照する必要があります(したがって、enabledelayedexpansionをスクリプトの先頭として)

2
VonC

パスにスペースが含まれている場合は、%~s1を使用してみてください。これにより、スペースが削除され、~1がパスに追加されます。さらに重要なことは、ファイルの絶対パスを指します。使ってみてください。

2
Prabhu RK