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

时间:2012-08-22 16:30:09

标签: 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
)

基本上,我在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)

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

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

(同样,两个单独的“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!

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

C:\Somedir>_

我得到了

_

我需要手动输入“echo on”以获取再次显示的路径。我哪里出错了?

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

1 个答案:

答案 0 :(得分:12)

我现在看到你的问题了 - 这是一个有趣的问题。您正在批处理文件中调用批处理文件而不使用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状态将保持关闭状态,父批次将从正常停止的位置恢复。

我还改进了解析逻辑和引号使用的参数。在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
)