我一直讨厌批处理,我仍然这样做,即使是最简单的事情,我更喜欢C或PHP/Perl.但这次我不能没有它,****叹气****.
我想将echo命令重定向到另一个命令.例如:
echo example | more
Run Code Online (Sandbox Code Playgroud)
但我也希望能够在管道的回声部分使用特殊字符:
echo & | more
Run Code Online (Sandbox Code Playgroud)
这当然没有用.所以我尝试过:
echo ^& | more
Run Code Online (Sandbox Code Playgroud)
哪个也没用.然后通过反复试验我发现:
echo ^^^& | more
Run Code Online (Sandbox Code Playgroud)
那很有效.但作为感兴趣的程序员我想知道为什么.为什么没有^&工作^^^&呢?
我在XP Pro SP3系统上创建的BAT文件每次都能完美运行.
安装在另一个XP [也是Pro SP3]系统上,每次都会失败("挂机").
问题结果是在多步管道中.为了隔离它,我一直在简化,直到我到达这个最小的[和人工]测试用例
echo. | date | find "/" | find "/" | find "/"Run Code Online (Sandbox Code Playgroud)
注意:前两个步骤没有缩短,date /t因为一些用户的系统是XP之前的[因此缺少Command Extensions].另外:仔细测试显示date正在执行MS-DOS内部DATE命令并find执行在"C:\ WINDOWS\system32 \"中找到的香草"FIND.EXE,2004年8月4日,9216"[和"中的安全副本相同" C:\ I386 \".
在失败的系统上,每个具有4个或更多个| s的命令在第五步中挂起,即使在这里 - 这里 - 程序很简单,它们处理的文本量也很小.
昨天我在用户的系统上做了一些进一步的测试,发现了一个我不知道的微妙之处.我在命令提示符下输入了简化命令[上面].按预期失败["挂起"].但是,当我重新启动并在做任何事情之前再次尝试[在用户的正常操作中永远不会发生的情况]时,我感到震惊:它工作[即,MS-DOS DATE命令的输出按预期显示].它再次起作用.然后在第三次尝试时,故障模式重新出现,之后保持一致.
我确认这files=40对两个系统都有效,并放弃了.我仍然很好奇,但我不能花很多时间在一个小型项目上为一个无偿客户端分析我可以轻松解决的问题.
感谢大家,感谢您快速有效的回复.
在原始系统上,无论调用哪些程序以及它们正在处理多少文本[原因],具有4个或更多个| s的命令都能正常工作.
一旦确定了限制,就会有许多琐碎的解决方法,所以我的问题只是好奇心:有人可以提出限制的来源以及是否有[在XP中]会提高/消除它的设置?
注意:两个系统上都不存在HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\AutoRun和HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun.
另外:我为通过反复编辑我的原始帖子来回答评论而道歉,但无论我使用哪个浏览器登录,"添加评论"弹出窗口[或其应该是什么]都不会出现.也许我的理解是在我自己的帖子中添加评论不需要声望点是错误的.但是,现在我看到"show#more comments"也没有用.
最后:我使用这个网站的问题[主要症状是javascript控制台消息"Uncaught ReferenceError:StackExchange未定义"]与此处讨论的相同https://meta.stackexchange.com/questions/117730/stack-overflow-onclick-actions-broken- about一年前.
我正在维基百科上查看叉炸弹,批量示例如下:
%0|%0
Run Code Online (Sandbox Code Playgroud)
要么
:here
start ''your fork bomb name''.bat
goto here
Run Code Online (Sandbox Code Playgroud)
要么
:here
start %0
goto here
Run Code Online (Sandbox Code Playgroud)
我理解了第二个,他们开始了另一个自己的实例,然后重复,但我不明白第一个.我读到管道执行右边的文件,文件的输出在左边.叉炸弹为什么不能成为:
%0
Run Code Online (Sandbox Code Playgroud)
我会假设这会调用自己,但然后立即终止,但为什么不会%0|%0终止?即使新实例将继续创建新实例,但是在开始第二次实例后不是第一次完成吗?是什么让第一个继续?
编辑:是否循环,因为在返回递归调用之前,所有实例都无法终止?这是否意味着它只会调用第一个%0?
C:\>type c:\output.txt
abcd
C:\>type c:\output.txt | set /p V1=
C:\>set
... A bunch of junk, NOT seeing "V1"
Run Code Online (Sandbox Code Playgroud)
发生了什么?根据SET我见过的所有文档,%V1%应该从上面分配了"abcd"的值,不是吗?
如果重要的话,我使用的是Windows XP Pro,SP3.
在回答这个问题时,我发现了一些我没有解释的奇怪行为
for /f "delims=" %a in ('(for /l %z in (1,1,10^) do @echo %z^)') do @echo %a0
Run Code Online (Sandbox Code Playgroud)
您将看到数字10..100,现在只需添加管道,例如,sort或者more,或者:
for /f "delims=" %a in ('(for /l %z in (1,1,10^) do @echo %z^)^|sort') do @echo %a0
Run Code Online (Sandbox Code Playgroud)
%a和之间会有空格0!看起来像通过管道回声的东西增加了一个尾随空格,可以很容易地看到:
>_tempfile echo no space here
>_tempfile echo and here's a space|more
Run Code Online (Sandbox Code Playgroud)
乃至
>_tempfile <nul set /p =also a space|sort
Run Code Online (Sandbox Code Playgroud)
(可能使用echo来打印提示)
当没有输出重定向(无论是文件还是命令)时,都不会发生这种情况.这是一个错误还是我错过了什么?我如何摆脱空间?(除了剥去最后一个角色的肮脏黑客var:~0,-1)
我有这个简单的测试脚本:
echo start
falsey ^
&& echo nope
echo end
Run Code Online (Sandbox Code Playgroud)
falsey是一个微小的C程序,我帮助测试,它只是返回1:
int main(int argc, const char** argv) {
return 1;
}
Run Code Online (Sandbox Code Playgroud)
问题是,当我打开cmd并运行这个批处理脚本时,它会在两个&s 之间插入几个空格,这自然会导致它错误地回显nope:
C:\jenkins-foo-test>foo.bat
C:\jenkins-foo-test>echo start
start
C:\jenkins-foo-test>falsey & & echo nope
nope
C:\jenkins-foo-test>echo end
end
Run Code Online (Sandbox Code Playgroud)
我已经找到了一些解决方法,例如在以下位置引用引号&&:
falsey ^
"&&" echo nope
Run Code Online (Sandbox Code Playgroud)
在这种情况下,行情实际上并不起作用,请参阅@ dbenham的答案.
放弃^并合并两条线:
falsey && echo nope
Run Code Online (Sandbox Code Playgroud)
或者在前面添加一个空格&&:
falsey ^
&& echo nope
Run Code Online (Sandbox Code Playgroud)
这三个选项中的每一个都无法正确打印nope.但是当cmd.exe打印出正在运行的命令时,它们仍然会有额外的空格.
那么为什么要插入这些额外的空间?如何阻止cmd.exe破坏事物而不必一直将我的代码扭曲成温和不自然的形状?
假设存在执行另一个批处理文件(被调用者)的批处理文件(调用者),则call需要使用该命令以便在被调用者完成执行后返回调用者.这是一个例子:
caller.bat:
echo Calling another script...
call callee.bat
echo Returned from callee...
Run Code Online (Sandbox Code Playgroud)
callee.bat(在同一地点):
echo Being called from caller...
Run Code Online (Sandbox Code Playgroud)
输出将是这个(省略命令echos),表明执行按预期返回:
Run Code Online (Sandbox Code Playgroud)Calling another script... Being called from caller... Returned from callee...
如果call命令在调用者中被解除,则输出将为:
Run Code Online (Sandbox Code Playgroud)Calling another script... Being called from caller...
但是一旦被调用者涉及管道(|),则call命令是否被使用没有区别.例如:
caller.bat(被调用者保持不变):
echo Calling another script...
break | callee.bat
echo Returned from callee...
Run Code Online (Sandbox Code Playgroud)
输出将是这个,虽然没有call命令.
Run Code Online (Sandbox Code Playgroud)Calling another script... Being called from caller... Returned from callee...
这种行为的原因是什么,导致执行返回给调用者的原因是什么?
我正在编写自己的简单系统,允许我在 APK 上传到 GPlay 之前自动对其进行签名。我有一个可以进行签名的批处理文件;和一个“包装器”批处理文件,其内容将由 Jenkins 构建后在命令行上运行。
签名APKS.bat:
@echo off
set /p job= "Enter job name: "
set /p alias= "Enter key alias: "
set /p mobile= "Sign mobile? (y/n): "
set /p wear= "Sign wear? (y/n): "
echo.
echo "%job%"
echo "%alias%"
echo "%mobile%"
echo "%wear%"
[the rest of the code is sensitive so is emitted, but these variables are used later]
Run Code Online (Sandbox Code Playgroud)
包装代码:
@echo off
(echo test
echo test
echo y
echo y)| call sign_apks.bat
Run Code Online (Sandbox Code Playgroud)
本文向我展示了如何将值通过管道传输到程序中。引用答案:
Multiple lines …Run Code Online (Sandbox Code Playgroud) 背景:
我曾经回答过这个问题
,即将两个输入字符串从Java进程刷新到批处理脚本.由于我找到了一个解决方案解决方案,我仍然非常有兴趣解决剩下的谜团,并找出明显解决方案无效的原因.
问题描述
看到这个非常简单的批处理脚本
@ECHO OFF
SET /P input1=1st Input:
SET /P input2=2nd Input:
ECHO 1st Input: %input1% and 2nd Input: %input2%
Run Code Online (Sandbox Code Playgroud)
如果您使用Java运行此批处理脚本ProcessBuilder并将两个输入字符串刷入其中,您会注意到只会消耗第一个输入字符串,而忽略第二个输入字符串.我发现该SET /P命令消耗了来自管道的输入
我接受的解决方法基于最后两个选项,Thread.sleep(100)在输入之间使用语句或对每个输入使用1024字节缓冲区.
它始终适用于单个输入,或者在这种情况下是第一个输入,因为关闭流具有批处理脚本读取一个输入并且空返回所有后续SET /P语句的效果.
问题
为什么使用CRLF令牌的第一个选项"input\r\n"不起作用?
研究
我已经尝试String.getBytes()通过自己创建一个字节缓冲区\x0d并使用\x0aCRLF令牌的最后字节来解决该方法,但它没有任何效果.
我尝试了所有其他OutputStream包装器,PrintWriter以检查实现是否存在问题flush()而没有任何成功.
我创建了一个C++程序,它基本上与java程序一样,使用CreateProcess和stangely它就像一个魅力.
测试代码
不工作的Java代码:
ProcessBuilder builder = new ProcessBuilder("test.bat");
Process process = builder.start();
OutputStream out = process.getOutputStream();
out.write("foo\r\n".getBytes());
out.flush();
out.write("bar\r\n".getBytes()); …Run Code Online (Sandbox Code Playgroud) 在试图为为什么FindStr返回未找到问题提供全面的答案时,我遇到了涉及管道的代码的奇怪行为。这是一些基于原始问题的代码(将在批处理文件中执行):
rem // Set variable `vData` to literally contain `...;%main%\Programs\Go\Bin`:
set "vData=...;%%main%%\Programs\Go\Bin"
set "main=C:\Main"
echo/%vData%| findstr /I /C:"%%main%%\\Programs\\Go\\Bin"
Run Code Online (Sandbox Code Playgroud)
这并没有返回匹配,因此没有什么呼应和ErrorLevel被置1 1。
尽管当我逐步进行解析过程时,我得出相反的结论,但是我确实期望有一个匹配项和一个匹配ErrorLevel项0,因为:
首先,将对整个行进行解析,然后进行即时(%)扩展,因此%vData%将其扩展并%%替换为%,从而将执行以下命令行:
echo/...;%main%\Programs\Go\Bin| findstr /I /C:"%main%\\Programs\\Go\\Bin"
Run Code Online (Sandbox Code Playgroud)管道的每一端|都在自己的新cmd实例中执行cmd /S /D c,这两个实例均在cmd上下文中运行(这会影响%-expansion的处理),从而产生以下部分:
管道的左侧:
echo/...;C:\Main\Programs\Go\Bin
Run Code Online (Sandbox Code Playgroud)管道的右侧:
findstr /I /C:"C:\Main\\Programs\\Go\\Bin"
Run Code Online (Sandbox Code Playgroud)
(即搜索字符串findstr最后采用的是C:\Main\Programs\Go\Bin作为\即使在文字搜索模式用作转义字符,/C或/L) …