批处理文件echo on/off无法正常工作

Phi*_*Bel 5 batch-file

我不是很习惯制作批处理文件,所以我可能做错了什么,但我真的遇到了关闭/关闭的问题.(也就是说,如果你发现我错过了任何其他错误,请随意指出)

这是我的代码的简化版本:

@echo off
setlocal
set args=
set dir="."

:getargs
IF "%2"=="" (
    set dir="%1"
    goto callbatch
)
set args=%args% %1
shift
goto getargs

:callbatch
for %%f in (%dir%\*.txt) do (
    echo processing %%f
    "%BATCHHOME%\batch.bat %args% %%f
    echo
)
Run Code Online (Sandbox Code Playgroud)

所以基本上,我在BATCHHOME中有一个批处理文件,它对单个txt文件做了一些事情,我想生成一个批处理文件来处理给定目录中的所有txt文件.循环中唯一的回声是为了更好地说明问题.

现在,这是我遇到问题的地方.输出如下:

processing foo\text1.txt
some output from batch.bat
ECHO is on.

C:\somedir>(
echo processing foo\text2.txt
   "C:\the\path\of\batch.bat" the arguments here foo\text2.txt
)
ECHO is on.

C:\somedir>(
echo processing foo\text3.txt
   "C:\the\path\of\batch.bat" the arguments here foo\text3.txt
)
ECHO is on.

(etc)
Run Code Online (Sandbox Code Playgroud)

好的...我不知道为什么我正在调用的批处理文件会响应,但我没有成功,所以我每次都会把它关掉!我把最后一部分改为:

:callbatch
for %%f in (%dir%\*.txt) do (
    echo processing %%f
    "%BATCHHOME%\batch.bat %args% %%f
    echo off
)
echo
echo on
echo
echo Finished!
Run Code Online (Sandbox Code Playgroud)

(同样,两个单独的"echo"用于调试)所以现在输出如下所示:

processing foo\text1.txt
some output from batch.bat
processing foo\text2.txt
some output from batch.bat
processing foo\text3.txt
some output from batch.bat
(etc.)
ECHO is off.
ECHO is on.
Finished!
Run Code Online (Sandbox Code Playgroud)

这几乎是完美的,但有点奇怪.如果启用了echo,那么它为什么会显示"Finished!" 而不是"回声完成!"?然而,更大(但相关)的问题是当批处理文件完成时,我不再显示我的路径了.换句话说,而不是:

C:\Somedir>_
Run Code Online (Sandbox Code Playgroud)

我得到了

_
Run Code Online (Sandbox Code Playgroud)

我需要手动输入"echo on"以获得再次显示的路径.我哪里做错了?

编辑:为了澄清,我知道"回声"本身会打印回声的当前状态.这就是我的意图.在第一个代码中,它们表示在调用另一个批处理文件后,echo会神秘地打开.在第二个中,它表明批处理文件的末尾是echo,但行为就好像不是.这是我的问题.

dbe*_*ham 14

我现在看到你的问题了 - 这是一个有趣的问题.您正在批处理文件中调用批处理文件而不使用CALL.

如果批次A在没有CALL的情况下执行批次B,则批次B完成后整个批处理将终止 - 批次A将不会从停止的位置恢复.一旦批处理终止,ECHO状态将返回到批处理开始之前存在的原始状态,通常为ON.

但是你的场景有点复杂,因为你对第二批的"调用"是在一个FOR循环内.因此FOR循环继续执行缓存在内存中的DO命令,即使批处理已终止.这些命令现在在ECHO ON的命令行上下文中执行.

在第二种情况下,您在FOR DO块中明确关闭ECHO.在第一次"调用"之后,您再次处于命令行上下文中,然后关闭ECHO.因此,您需要手动打开ECHO.

我不确定FOR循环后的行是如何执行的.你说你已经简化了代码,所以我假设你实际运行的代码在某些代码块中也有这些额外的行.然后,这些行将被缓冲,并且即使在批处理终止之后仍然会执行.这也可以解释为什么打印"完成!"的行.即使ECHO开启,也不会回显.代码块中的所有命令都使用在输入最外面的代码块之前存在的ECHO状态.一个例外是FOR DO块使用在进入DO块之前存在的ECHO状态.

您发布的这两组代码都不会运行,因为每个代码都在"调用"第二个批处理文件的行中有一个不平衡的引用.

修复是简单地将CALL添加到执行第二批文件的语句中.然后批处理将继续,ECHO状态将保持为OFF,并且父批将在正确停止的位置恢复.

我还改进了解析逻辑和引号使用的参数.您应该~在explitly添加自己的参数之前使用每个参数的引号.该论点可能已经有了自己的引用.并且只要文件名或路径作为参数传递,就应该引用它,以防它包含空格或特殊字符.您需要跟踪变量中的值是否被引用.我通常发现更容易保持我的变量值不加引号,然后在需要时显式添加引号.

@echo off
setlocal
set args=
set "dir=."

:getargs
IF "%~2"=="" (
    if "%~1" neq "" set "dir=%~1"
    goto callbatch
)
set args=%args% %1
shift
goto getargs

:callbatch
for %%f in ("%dir%\*.txt") do (
    echo processing %%f
    call "%BATCHHOME%\batch.bat" %args% "%%f"
    echo
)
Run Code Online (Sandbox Code Playgroud)