为什么 XCOPY /W 和 REPLACE /W 为它们的单字符提示消耗所有重定向的文本数据?

Why do XCOPY /W and REPLACE /W consume all redirected text data for their one-character prompt?

当文本文件 test.txt 包含此内容时1:

test
data

下面的代码returns去掉第一个字符的文本文件的内容:

< "test.txt" (
    > nul pause
    findstr "^"
)

使用管道时也会发生同样的情况:

type "test.txt" | (
    > nul pause
    findstr "^"
)

因为pause命令正好占用一个字符。

然而,当用以下任一命令替换 pause 命令时,输出为空,尽管 - 像 pause - 他们提示 (/W) 输入单个字符只有:

这是为什么,这里发生了什么?
xcopy /Wreplace /W 是否消耗所有 redirected/piped 文本数据,甚至是多行,尽管它们只显示接收到的第一个字符?他们在乱弄文件指针吗?
有没有办法防止这些命令吸收多个字符?


1 ... 最后一行以换行符终止,以便 findstr 不会无限期地挂起 – 请参阅此线程:What are the undocumented features and limitations of the Windows FINDSTR command?,第 »FINDSTR 在 XP 和 Windows 7 上挂起,如果重定向的输入不以 <LF>«.

结尾

重定向与管道之间的行为实际上有所不同。

重定向

似乎 XCOPY 和 REPLACE 只是将标准输入文件指针移动到文件结尾 (EOF)。

如果您使用 FIND /V "" 而不是 FINDSTR "^",那么您将得到整个文件作为输出,因为 FIND 在启动时将文件指针重置为文件的开头。所以XCOPY运行后stdin流仍然有效,但是文件指针在EOF。

XCOPY 必须在没有实际读取所有数据的情况下移动文件指针,因为当我使用包含 0.5 GBytes 的 big.txt 时,它仍然是“瞬时的”。如果 XCOPY 在继续之前必须读取所有文件,将会有明显的延迟。

管道

我不完全理解这意味着什么,但我相信标准管道是块缓冲的。 XCOPY 和 REPLACE 在继续之前最多读取 1 个完整块,将剩余的管道数据留给 FINDSTR 读取。

我输入了一个包含 4191 个字节的 127 行文件,FINDSTR 在 3 行中输出了 97 个字节。所以在这种情况下,XCOPY 似乎读取了 4094 个字节。

然后我在没有任何新行的情况下输入了一个 5000 字节的文件,FINDSTR 输出了 908 字节,这意味着 XCOPY 似乎读取了 4092 字节。

所以管道块缓冲区必须在 4 kbytes 附近的某个地方。我的猜测是 XCOPY 只是将文件指针移动到当前缓冲区的末尾而不读取所有数据,但我不知道如何测试它。

正如预期的那样,用 FIND 代替 FINDSTR 不会改变使用管道时的结果 - 在读取数据后,无法将文件指针重置回管道数据的开头。


我无法想象有什么方法可以修改 XCOPY 或 REPLACE 的行为...就是这样。

至于为什么 XCOPY 和 REPLACE 的行为方式是这样的?......我没有任何线索。微软的“批处理”世界是如此奇特,我早就放弃了问为什么。