windows – 为什么我不能按顺序重定向到两个输入流`0 <`和`3
当我尝试将多个文件重定向到多个流时,如下例所示,一切都按预期工作:
3< stream3.txt 4< stream4.txt echo/ 这样的东西也可以使用更多的流和文件以及除echo /甚至功能代码块之外的其他命令.即使使用保留的输出流1和2似乎也能正常工作. 但是,只要我按照给定的顺序使用以下流执行此操作: 0< stream0.txt 3< stream3.txt echo/ 托管命令提示符实例立即关闭. 当我更改流的顺序时,它再次正常工作: 3< stream3.txt 0< stream0.txt echo/ 那么,当我尝试按顺序输入重定向到流0和3时,为什么cmd实例意外终止? 我使用的是Windows 7(x64). 在我尝试执行上述失败的输入重定向之前,我用cmd打开一个新的命令提示符实例: cmd 0< stream0.txt 3< stream3.txt echo/ 我可以读取出现的错误消息 – 假设文本文件包含其基本名称后跟换行符:
当我执行以下操作时,我可以看到两个文件实际上都被重定向: cmd /V 0< stream0.txt 3< stream3.txt (set /P #="" & echo/!#!) cmd /V 0< stream0.txt 3< stream3.txt (<&3 set /P #="" & echo/!#!) 各自的输出: stream0 和: stream3 这到底是怎么回事?
注意:这是对cmd内部发生的事情的简化
执行重定向命令. 让我们从指示的命令开始 0< file1 3< file2 echo/ 该命令被解析并在内存中创建所需重定向的表示,某种表/列表将保存有关重定向的信息:哪个句柄被重定向,旧保存的句柄,重定向时句柄应指向的位置,… Redirection requests ------------------------------- redirect saved redirectTo +--------+--------+------------ R1 | 0 file1 | R2 | 3 file2 此时(解析命令后)没有更改流. 还有一个系统表,用于处理每个文件描述符(在我们的示例中为cmd流)确实指向的位置. File descriptors ------------------ points to +----------------- 0 | stdin 1 | stdout 2 | stderr 3 | 4 | 注意事实并非如此,底层结构有点复杂,但这样更容易看出它是如何工作的 当要执行该命令时,将调用内部SetRedir函数.它迭代先前的重定向请求表,保存现有句柄并创建所需的新句柄.最初的状态是 Redirection requests File descriptors ------------------------------- ------------------ redirect saved redirectTo points to +--------+--------+------------ +----------------- R1 | 0 file1 0 | stdin | 1 | stdout R2 | 3 file2 2 | stderr 3 | 4 | 检索来自重定向请求表(R1)的第一个元素,将流0重定向到file1的请求.有必要保存当前句柄以便以后能够恢复它.对于此操作,使用 R1[saved] = _dup( R1[redirect] ); _close( R1[redirect] ); Redirection requests File descriptors ------------------------------- ------------------ redirect saved redirectTo points to +--------+--------+------------ +----------------- R1 | 0 3 file1 0 | --- | 1 | stdout | R2 | 3 file2 2 | stderr | 3 | stdin <<--/ 4 | 保存后,通过打开请求的文件完成重定向 _dup2( CreateFile( R1[redirectTo] ),R1[redirect] ); Redirection requests File descriptors ------------------------------- ------------------ redirect saved redirectTo points to +--------+--------+------------ +----------------- R1 | 0 3 file1 0 | file1 <<--- | 1 | stdout R2 | 3 file2 2 | stderr 3 | stdin 4 | 第一次重定向已经完成.现在是时候做同样的操作了 R2[saved] = _dup( R2[redirect] ); _close( R2[redirect] ); Redirection requests File descriptors ------------------------------- ------------------ redirect saved redirectTo points to +--------+--------+------------ +----------------- R1 | 0 3 file1 0 | file1 | 1 | stdout R2 | 3 4 file2 2 | stderr 3 | --- 4 | stdin <<--/ 通过打开输入文件并将其与文件描述符相关联来完成重定向 _dup2( CreateFile( R2[redirectTo] ),R2[redirect] ); Redirection requests File descriptors ------------------------------- ------------------ redirect saved redirectTo points to +--------+--------+------------ +----------------- R1 | 0 3 file1 0 | file1 | 1 | stdout R2 | 3 4 file2 2 | stderr 3 | file2 <<--- 4 | stdin 重定向已完成,执行命令时,流0重定向到file1,流3重定向到file2. 完成后,是时候恢复这个过程了. ResetRedir()函数处理操作.它再次使用_dup2()函数将保存的句柄传输到原始文件描述符.这里出现问题,因为保存的描述符已更改 _dup2( R1[saved],R1[redirect] ); R1[saved] = null; Redirection requests File descriptors ------------------------------- ------------------ redirect saved redirectTo points to +--------+--------+------------ +----------------- R1 | 0 file1 0 | file2 <<-- | 1 | stdout | R2 | 3 4 file2 2 | stderr | 3 | ---/ 4 | stdin 现在,使用第二个重定向完成相同的操作 _dup2( R2[saved],R2[redirect] ); R2[saved] = null; Redirection requests File descriptors ------------------------------- ------------------ redirect saved redirectTo points to +--------+--------+------------ +----------------- R1 | 0 file1 0 | file2 | 1 | stdout R2 | 3 file2 2 | stderr 3 | stdin <<-- 4 | ---/ 一旦移除了重定向,& 0句柄指向file2,stdin流存储在& 3中.这可以作为测试 @echo off setlocal enableextensions disabledelayedexpansion >file1 echo This is file 1 >file2 echo This is file 2 echo Test 1 - trying to read from stdin after redirection cmd /v /c"( 0< file1 3< file2 echo - test1 ) & set /p .=prompt & echo !.!" echo( echo( echo Test 2 - trying to read from stream 3 after redirection cmd /v /c"( 0< file1 3< file2 echo - test 2 ) & <&3 set /p .=prompt & echo !.!" 这将产生 W:&;testRedirection.cmd Test 1 - trying to read from stdin after redirection - test1 prompt This is file 2 Test 2 - trying to read from stream 3 after redirection - test 2 prompt This is typed text This is typed text W:&; 可以看出,在第一次测试中,set / p已从file2读取,并且在第二次测试中,尝试从& 3读取stdin流. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- windows-server-2008 – IIS7 Windows Server 2008 FTP –
- windows-server-2008-r2 – 使用SAN LUN的跨区卷的注意事项
- windows – 如何使用robocopy删除超过30天的文件?
- windows-installer – 卸载软件时如何删除HKCU注册表项?
- Windows 2008 R2服务器可以加入2003域吗?
- 图解 -- Win10 OpenSSH
- windows – WinInet vs WinHttp(服务或类似服务的过程)
- .net – 在Windows Phone 8中阅读Windows-1252编码
- windows – 如何修复pyCharm安装?
- windows-server-2012 – 无法访问Windows Server 2012(以太