时间:2018-12-10 00:20:47

标签: batch-file

我正在为课堂上的第六次作业编写批处理脚本,当我几乎完成时,我遇到了麻烦。 (我们通常专注于bash脚本编写,因此我是新手)

该脚本在首次运行时可根据需要运行;但第二次运行时的行为有所不同。

本质上,脚本会检查参数的值(如果存在)并根据该值运行特定的代码。例如,如果参数为“ 1”,则它将检查目录的PATH变量,并在目录不存在,目录是否存在的情况下创建该目录-不会发生任何事情,它将继续执行脚本。

在修改PATH之后第二次运行脚本时,会发生此问题。我收到输出“ \ Common此时不期望”。

我第一次运行脚本时遇到了类似的问题,但是设法通过在IF语句的评估两边都添加了引号来解决了该问题,但是现在我不确定在哪里继续执行此操作。

我的代码如下:

@echo on

IF "%1%" == "0" (
    SET "VAR1=%path%"
    echo.%VAR1%|findstr /C:"App0" >nul 2>&1
    if errorlevel 1 SET "PATH=%PATH%%cd%\App0;"
    if not errorlevel 1 echo Found
    goto errorBypass
) ELSE IF "%1%" == "1" (
    SET "VAR2=%path%"
    ECHO %VAR2%
    echo.%VAR2%|findstr /C:"App1" >nul 2>&1
    if errorlevel 1 SET "PATH=%PATH%%cd%\App1;"
    if not errorlevel 1 echo Found
    goto errorBypass
) ELSE IF "%1%" == "" (
    IF "%HUMBER_HOME%" == "" (
        goto Error2
    ) ELSE (
        CALL "HUMBER_HOME\bin\setEnv.bat"
        goto errorBypass
    )
)
echo HERE

:Error2
echo Error2

:errorBypass
call "run.bat"

此外,所以我知道以供将来参考-是否有行一步调试的有效方法?还是可以输出发生错误的特定行的命令?当在不同地方的多个问题引起一个错误时,我发现有些困难。

1 个答案:

答案 0 :(得分:2)

引用批处理文件参数

打开命令提示符窗口,然后运行call /?。输出帮助说明了如何引用批处理文件参数。 %1引用传递给批处理文件的第一个参数。例如,可以是1(不带引号的参数字符串),也可以是"1"(带引号的参数字符串)。 %~1引用第一个参数字符串,并删除了双引号。

在参数引用之后再添加一个%是错误的。语法%variable%用于引用环境变量的字符串值。批处理文件参数仅使用百分号和数字来引用,两者之间不带修饰符。数字后没有其他百分号。这也是为什么123,...不能用作环境变量名称的原因。

IF "%1%" == "0" (不好,因为这可能导致在执行命令行的过程中使用"1"作为第一个参数调用的批处理文件:

IF ""1"" == "0" (

更好的语法是IF "%~1" == "0" (,它会导致执行命令行:

IF "1" == "0" (

有关如何评估批处理文件参数的更多详细信息,请参见我对difference between “…” and x“…” in batch的回答。

将文件夹路径添加到本地PATH

环境变量PATH拥有文件夹路径的comma-separated list,其中列表分隔符是分号而不是逗号。

因此,;末尾的PATH意味着还有一个文件夹路径,它是一个空文件夹路径。可以在PATH的中间或结尾指定一个空的文件夹路径,但是由于PATH不应包含空的文件夹路径,所以这样做是不好的做法。

因此,代码中的以下命令行效果不佳:

if errorlevel 1 SET "PATH=%PATH%%cd%\App0;"

如果;尚未以分号结尾,则还会丢失PATH,这可能是第二次执行批处理文件时出现错误消息的原因。

更好的代码可以在下面完全修改的批处理文件代码中看到。

参考当前目录

可以使用%CD%来引用当前目录,该目录可以与%~dp0所引用的批处理文件目录不同。 %~dp0引用参数0的驱动器和路径,该参数是批处理文件本身。用%~dp0引用的批处理文件路径字符串始终以反斜杠结尾。因此,在%~dp0与文件/文件夹名称连接时,不应使用其他反斜杠。

动态环境变量CD通常以结尾没有反斜杠结尾。因此,在大多数情况下,%CD%必须与具有文件/文件夹名称的附加\串联。但是在批处理文件中使用%CD%时必须考虑一个例外:%CD%扩展为当前目录(驱动器的根目录)末尾带有\的字符串,例如C:\D:\。因此,始终需要使用%CD%来检查字符串是否已经以反斜杠结尾,然后再附加文件名/文件夹名称而没有附加反斜杠。

其他建议

在使用在命令块内定义/修改并在命令块内引用的环境变量时,应避免使用以(开头和以)结尾的命令块,因为这需要使用delayed expansion,如 IF 上的命令提示符窗口中运行set /?的帮助输出所解释,以及通常使用命令块的 FOR 示例。 Windows命令处理器被设计为主要用于执行另一个命令行。在某些情况下,使用命令块可以加快批处理文件的执行速度,但在许多情况下,最好避免使用它们。

请参见debugging a batch file并简要说明如何调试批处理文件。单步执行实际上是不可能的。但是cmd.exe显示在哪一行或命令块上发生了错误,导致退出批处理文件执行,并且是什么错误。

修订的批处理文件代码

这是修改后的批处理文件代码:

@echo off
goto Main

:AddPath
echo %PATH%;|%SystemRoot%\System32\findstr.exe /I /C:"\%~1;" >nul 2>&1
if not errorlevel 1 echo Found %~1 in PATH& goto :EOF
set "Separator=;"
if "%PATH:~-1%" == ";" set "Separator="
if "%CD:~-1%" == "\" (set "AppPath=%CD%%~1") else set "AppPath=%CD%\%~1"
set "PATH=%PATH%%Separator%%AppPath%"
set "AppPath="
set "Separator="
goto :EOF

:Main
if "%~1" == "0" call :AddPath App0 & goto errorBypass
if "%~1" == "1" call :AddPath App1 & goto errorBypass
if not "%~1" == "" goto RunApp
if "%HUMBER_HOME%" == "" goto Error2
if exist "%HUMBER_HOME%\bin\setEnv.bat" (
    call "%HUMBER_HOME%\bin\setEnv.bat"
    goto errorBypass
)

echo File "setEnv.bat" in subdirectory "bin" in directory
echo defined by environment variable HUMBER_HOME not found.
echo HUMBER_HOME directory: "%HUMBER_HOME%"
echo/
pause
goto :EOF


:RunApp
echo HERE
goto :EOF

:Error2
echo Error2
goto :EOF

:errorBypass
if exist "run.bat" call "run.bat"

在批处理文件顶部定义了子例程AddPath,这有点不寻常。因此,带有goto Main的第二行会导致在开始执行批处理文件时跳过子例程的代码。

调用子程序AddPath时,第一个参数为App0App10或{{1 }}。

"0"中的第一行输出局部环境变量1的当前值,并附加一个分号,并将此输出重定向到 FINDSTR ,后者会搜索不区分大小写的字符并按字面意义搜索第一个参数字符串在反斜杠后传递给子例程,并以分号结尾。附加的"1"AddPath应该避免对PATH中任何文件夹路径上的误报,也偶然在文件夹中间的某个位置包含\;路径。这种小的增强并不是100%故障安全的,但应该足够好。

FINDSTR 在行中找到的搜索字符串上以PATH退出。在这种情况下,仅输出一条信息消息,并退出子例程,这导致批处理文件的执行在之前已调用该子例程的主代码上继续进行。否则,必须将传递的应用程序名称添加到本地App0

另请参阅:

因此,首先将环境变量App1定义为0作为值。但是,如果本地PATH已经以反斜杠结尾(尽管不应),则环境变量将立即删除。请注意,如果Separator;结尾,则将PATH的最后一个字符与PATH进行比较的命令行可能会失败。因此,这个简单的版本并不是100%故障安全的。

接下来,根据当前目录是驱动器的根目录还是任何目录的子目录,当前目录路径将与传递的应用程序文件夹名称(不带或带有反斜杠)连接在一起。

然后,通过根据传递的参数附加应用程序路径来扩展本地;,而之前或之前没有附加分号。

最后,在退出子例程之前,删除不再需要的环境变量PATH"

所讨论的主要代码中的主要错误是调用分配给环境变量{的目录的子目录PATH中的批处理文件Separator时环境变量AppPath周围缺少百分号{1}}。这可能是第二次执行批处理文件时出现错误消息的另一个原因。

修改后的代码首先在调用之前检查每个要调用的批处理文件是否确实存在。

要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。

  • HUMBER_HOME
  • setEnv.bat
  • bin
  • HUMBER_HOME
  • call /?
  • echo /?
  • findstr /?