如果我重定向到批处理文件而不是调用它,为什么批处理文件不会保持可变
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%
。
我想实施 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%
。