5

我真的不习惯制作批处理文件,所以我可能做错了什么,但我真的遇到了关闭/打开回声的问题。(也就是说,如果您发现我遗漏的任何其他错误,请随时指出)

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

@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!

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

C:\Somedir>_

我只是得到

_

我需要手动输入“echo on”才能再次显示路径。我哪里做错了?

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

4

1 回答 1

16

我现在看到了你的问题 - 这是一个有趣的问题。您在不使用 CALL 的情况下从批处理文件中调用批处理文件。

如果批次 A 在没有 CALL 的情况下执行批次 B,那么一旦批次 B 完成,整个批次处理就会终止 - 批次 A 不会从中断的地方继续。一旦批处理终止,ECHO 状态将返回到批处理开始之前存在的原始状态,通常为 ON。

但是您的情况有点复杂,因为您对第二批的“调用”在 FOR 循环中。所以 FOR 循环继续执行缓存在内存中的 DO 命令,即使批处理已经终止。这些命令现在在 ECHO ON 的命令行上下文中执行。

在第二种情况下,您在 FOR DO 块中明确关闭 ECHO。在第一次“呼叫”之后,您再次处于命令行上下文中,然后您将 ECHO 关闭。因此您需要手动打开 ECHO。

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

您发布的两组代码都没有运行,因为每组代码在“调用”第二个批处理文件的行中都有一个不平衡的引号。

解决方法是简单地将 CALL 添加到执行第二个批处理文件的语句中。然后批处理将继续,ECHO 状态将保持关闭,父批处理将在正确停止的地方恢复。

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

@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
)
于 2012-08-22T23:22:38.020 回答