如果我重定向到批处理文件而不是调用它,为什么批处理文件不会保持可变

Why Batch File wouldn't remain variable if I redirect to it instead of call it

我想实施 OutTo.cmd 可以实现:

echo msg | OutTo.cmd var
echo %var%
msg

我的代码在 OutTo.cmd:

set /p %1=

@REM For check
echo %var%

当我运行 echo msg | OutTo.cmd var, 控制台将显示

msg

这意味着 "msg" 在 OutTo.cmd 运行ning

期间成功保存到 var

但后来我 运行 echo %var%, console display nothing, 这意味着 var 没有定义,在 OutTo.cmd

之后

但是如果我 运行 OutTo.cmd 如下:

OutTo.cmd var

并输入:

msg

在 OutTo.cmd 完成后,var 的值将保持不变:

echo %var%

显示

msg

会的,我知道最简单的方法是:

echo msg > tmp
set /p newvar=<tmp

所以我很好奇,如果我调用它,为什么 batch 会保持可变 但如果我将输出重定向到它就不会?

Test.cmd

@echo off
setlocal enabledelayedexpansion

echo Test.cmd
echo !cmdcmdline!

echo Call OutTo.cmd
call OutTo.cmd

echo Pipe to OutTo.cmd
echo msg | OutTo.cmd

echo Pipe to OutTo.cmd using call
echo msg | call OutTo.cmd

OutTo.cmd

@echo off
setlocal enabledelayedexpansion

echo(!cmdcmdline!

输出:

Test.cmd
cmd  /c Test.cmd
Call OutTo.cmd
cmd  /c Test.cmd
Pipe to OutTo.cmd
C:\Windows\system32\cmd.exe  /S /D /c" OutTo.cmd"
Pipe to OutTo.cmd using call
C:\Windows\system32\cmd.exe  /S /D /c" call OutTo.cmd"

此示例用于显示管道而不是管道发生的情况。

用于执行的命令Test.cmd:

cmd /c Test.cmd

使用 enabledelayedexpansion 以便 !cmdcmdline! 的回显不会在命令行中出现 & 或其他未加引号的特殊字符时引起问题。

关于输出:

  • 第一个命令行来自 Test.cmd 本身。
  • 第二个命令行是 call OutTo.cmd 来自 Test.cmd。与第一个相同的过程。
  • 第三条命令行正在传送到 OutTo.cmd。与 1st 和 2nd 不是同一个进程,它是一个子进程。
  • 第 4 个命令行通过 call 管道连接到 OutTo.cmd。与 1st 和 2nd 不是同一个进程,它是一个子进程。

第三个和第四个将在 /c 之后从命令中去除外部引号,因为使用 /S 并且自动 运行 命令被禁用,因为使用 /D

第 4 个已过时,因为不需要在 /c 之后使用 call。它作为 cmd.exe.

的单独实例执行

管道导致一个单独的过程,因为管道是一个过程管道到另一个过程。 cmd.exe 被执行到 运行 OutTo.cmd 作为要通过管道传输到的子进程。

子进程可以从父进程继承。父进程不能继承子进程。最后一个陈述是为什么当您试图从子进程中获取它时无法使用 OP 中设置的值获取 %var%