将带空格的路径作为bat文件的参数传递

时间:2009-01-23 14:42:54

标签: command parameters batch-file

我有一个简单的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>

8 个答案:

答案 0 :(得分:98)

使用"%~1"。仅%~1会删除周围的引号。但是,由于您无法知道输入参数%1是否有引号,因此您应该"%~1"确保它们已被添加。这在连接变量时特别有用,例如: convert.exe "%~1.input" "%~1.output"

答案 1 :(得分:19)

有趣的一个。我喜欢在cmd / command中收集有关引号处理的引号。

使用%1而不是“%1”来修复您的特定脚本!!!

通过添加'echo on'(或摆脱回声),你可以很容易地找到它。

答案 2 :(得分:14)

我认为OP的问题是他想要做以下的 BOTH

  • 传递可能包含空格的参数
  • 测试参数是否缺失

正如几张海报所提到的,要传递包含空格的参数,必须用双引号括住实际参数值。

为了测试参数是否缺失,我总是学到的方法是:

if "%1" == ""

但是,如果引用实际参数(如果值包含空格必须是这样),则变为

if ""actual parameter value"" == ""

导致“意外”错误。如果您改为使用

if %1 == ""

然后引用值不再出现错误。但在这种情况下,当值缺失时,测试不再有效 - 它变为

if  == ""

要解决此问题,请使用任何其他字符(除了对DOS有特殊含义的字符)而不是测试中的引号:

if [%1] == []
if .%1. == ..
if abc%1xyz == abcxyz

答案 3 :(得分:6)

“%〜1”大部分时间都可以使用。但是,您需要注意以下几点:

  1. Windows NT 4.0不支持。您需要Windows 2000或更高版本。 (如果您要编写与旧操作系统兼容的脚本,请注意。)
  2. 它不会使参数安全和消毒。我的观察是无法正确清理CMD脚本中的命令行参数
  3. 为了证明第二点,让我举一个例子:

    REM example.cmd
    ECHO %~1
    

    使用example.cmd dummy^&DIR运行。 &符号在此转义(^&)以防止shell作为命令分隔符进行解释,以便它成为传递给脚本的参数的一部分。 DIR被解释为运行脚本的子shell中的命令,它不应该在那里。

    引用它可能会有一段时间,但仍然不安全:

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

    example2.cmd foo^"^&DIR^&^"bar会打破它。 DIR命令将运行两次,一次在SET之后,另一次在第一次ECHO之后。你看到你认为被引用的"%~1"被引用本身没有引用。

    因此,无法使解析参数安全。

    (编辑:EnableDelayedExpansion在Windows NT 4中也不起作用。感谢此处的信息:http://www.robvanderwoude.com/local.php

答案 4 :(得分:5)

如果您有一个带空格的路径,则必须用引号(“)包围它。

不确定这是不是你要问的那个?

答案 5 :(得分:2)

@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',
  • 后跟一个空字符串(""

但请注意,如果您需要在PWA_PATH子句中使用IF,则需要引用!PWA_PATH!(因此enabledelayedexpansion作为脚本的开头)

答案 6 :(得分:2)

如果您的路径包含空格,请尝试使用%~s1。这将删除空格并将~1附加到您的路径,更重要的是它指的是文件的绝对路径。尝试使用它。

答案 7 :(得分:0)

假设您想通过从 C# 代码中执行批处理文件来备份数据库。这是一个完全有效的解决方案,用于处理路径内的空白空间。 这适用于 Windows。不过我还没有用单声道测试过。

C# 代码:

        public bool BackupDatabase()
    {
        bool res = true;
        string file = "db.bat";
        if (!File.Exists(file)) return false;

        BackupPaths.ForEach(path =>
        {
            Directory.CreateDirectory(path);

            string filePath = Path.Combine(path, string.Format("{0}_{1}.bak", Util.ConvertDateTimeToFileName(false), DatabaseName));
            Process process = new Process();
            process.StartInfo.FileName = file;
            process.StartInfo.Arguments = string.Format(" {0} {1} \\\"{2}\\\""
                , DBServerName
                , DatabaseName
                , filePath);

            process.StartInfo.WindowStyle = ProcessWindowStyle.Normal;

            try
            {
                process.Start();
                process.WaitForExit();
            }
            catch (Exception ee)
            {
                Logger.Log(ee);
                res = false;
            }
        });
        return res;
    }

这里是批处理文件:

@echo OFF
set DB_ServerName=%1
set Name_of_Database=%2
set PathToBackupLocation=%3

echo Server Name = '%DB_ServerName%'
echo Name of Database = '%Name_of_Database%'
echo Path To Backup Location = '%PathToBackupLocation%'

osql -S %DB_ServerName% -E -Q "BACKUP DATABASE %Name_of_Database% TO DISK=%PathToBackupLocation%"