首页 > 编程语言 > Windows cmd命令行输入输出重定向问题
2020
09-24

Windows cmd命令行输入输出重定向问题

最近学校的网比较搓,DNS天天挂,出口带宽天天堵,NAT后的总出口带宽也才4MB/s(来源:360测速),唉,不亲身体会鬼才知道一堆人共享这个带宽是什么感觉。
废话不多说了,在Unix下重定向用着感觉很high,现在想把win下的nslookup的错误提示“*** Can't find server name for address 10.3.9.5: Non-existent domain”一同导出到txt文件,搜了下,嗯,遂有此文。
再说句废话,windows这是赤裸裸的抄袭啊,stdio(0),stdout(1),stderr(2)都跟unix是一样的

重定向符号主要有:>,>>,<,>&,<&和|,以下只有前五个的介绍,最后一个是管道,与Unix亦完全一致。

第一节

首先从一个经典问题开始,“1>nul 2>nul”的意思是既屏蔽正常的输出又屏蔽错误的输出,那么我们马上就知道了这里的1表示正常输出(即所谓的“标准输出”--stdout),2表示错误输出(即所谓的“标准错误输出”--stderr)。

1和2其实是句柄stdout和stderr的数字代号,至于什么是句柄,我认为可以理解为某种事物的一种标识,或者说这个句柄指向某个事物。举个例子来说,“标准输出”以句柄stdout为标识,或者说句柄stdout指向“标准输出”。
还有一个句柄--stdin,它是所谓“标准输入”的标识,数字代号是0。除此之外还有3~9可用,只是它们没有定义。

“标准输出”和“标准错误输出”默认是要输出到控制台con(即cmd窗口)的,而“标准输入”默认是由控制台con(即键盘)输入的,因此重定向的目的就是将输入输出流从默认位置重定向到新的位置。符号“>”和“>>”的默认句柄代号是1,而“<”的默认句柄代号是0。

“echo hhhhhh”类似于这样的语句可以说是我们再熟悉不过的了,但这只是种默认的状态,其实里面还有一些内容。这一句完整的应该是这样的:“echo hhhhhh 1>con 2>con”,意思是将echo命令的结果中的标准输出和标准错误输出输出到控制台con中,只不过此时标准错误输出是空的。

再看一个例子,如果给dir一个错误的参数,例如“dir /mm”,那么写全了就是“dir /mm 1>con 2>con”,只不过此时的标准输出是空的。如果你这样写的话“dir /mm 1>hero.txt”,那么屏幕上会照常显示错误信息但hero.txt中不会有内容。

再来一个标准输入的例子,“set /p var= ”其实应该是这样的“set /p var= 0<con”,只是因为0<con是默认值可以省略。我们当然可以从文件中读取输入,如“set /p var= 0<file.txt”,0是默认值可以省略。

nul代表的是“空设备”,是一个不存在的设备,将输出流重定向到空设备就相当于屏蔽掉了一样。而如果从空设备中读取输入,自然是读不到东西的,但的确是输入了,这也就是“set /p var=<nul”中“<nul”相当于回车但不换行的原因。

第二节

下面要讲的是句柄代码之间的“重定向”。 之前不是提到过还有3~9这7个句柄数字代号吗,这些究竟有什么用?说实话,基本没什么用,因此建议你如果不是迫切想知道这部分内容的话就不要往下看了。

“echo hero 1>hero.txt”这一句是将标准输出重定向到文件hero.txt,相当于将句柄代号1的指向由con变为hero.txt。“echo hero 3>hero.txt 1<&3”,这句的结果是生成了文件hero.txt,其内容为hero,过程是这样的:“3>hero.txt”是将句柄数字代号 3的指向由“空”变为hero.txt;“1<&3”是将句柄数字代号3的指向复制给1的指向,此时1的指向就为hero.txt了,因此标准输出就被重定向到hero.txt中了。

“i<&j”和“i>&j”的效果都是把j的指向复制给i。“echo hero >hero.txt 2>&1”这句的意思是,无论是标准输出还是标准错误输出都会被重定向到hero.txt中,具体过程:1的指向由con转为 hero.txt,“2>&1”是把1的指向复制给2,此时2的指向也变为了hero.txt,因此1和2都会被重定向到hero.txt 中。注意:1是符号“>”的默认句柄数字代号。

再看“echo hero 3>hero.txt”,这个为什么就不能将结果重定向到文件中呢?记住,我们要重定向的只有标准输入、标准输出和标准错误输出,因此真正“干活” 的就只有0、1和2,因为它们分别指代了前面的三者,而3没有指代任何句柄只能作为间接量使用。

“more 3<hero.txt 0>&3”这句是显示文件hero.txt,具体过程:“3<hero.txt”把3的指向变为 hero.txt,“0>&3”把3的指向复制给0,即0指向了hero.txt(只不过这次是从hero.txt中读取数据)。强调一下,真正能读取数据的是0而不是3,3只是作为中间量而已。刚才这句我们当然可以这么写:“more 0<hero.txt”或直接“more <hero.txt”。

再来一个例子“echo hero 5>hero.txt 4>&5 3<&4 1<&3”,结果输出到了hero.txt中。具体过程:5的指向变成hero.txt,“4>&5”把5的指向复制给 4,“3>&4”把4的指向复制给3,“1>&3”把3的指向复制给1,最终1的指向就是hero.txt,则1所指代的标准输出就被重定向到了hero.txt。

第三节

注意:这一节的内容都是围绕着下面这个例子进行叙述的。

代码:

@echo off
echo 英雄是好男人!!!
echo 1>nul 3>nul
echo 英雄是
echo 英雄是
echo 这是怎么回事,难道就不能 1>con 4>con
pause

这究竟是怎么回事?为什么结果会如此出乎意料?
这里涉及到一个所谓“备份”的问题,就是在修改某个句柄代号的指向之前,系统会把该句柄代号原来的指向备份到截止到目前第一个指向为空的句柄代号中。目的是当这一行的程序结束之后,系统可以通过备份找回原来的指向。

( 在继续阅读之前建议你准备好纸笔,以便能记录下各个代号指向的变化,这样不至于混乱)
我们现在把焦点集中到这句“echo. 1>nul 3>nul”上来。这句究竟是如何工作的呢?

第一步:在运行“1>nul”之前,1的指向是默认值con,此时代号3~9的指向都是空(初始值),因此系统会把1的指向备份到3(因为3是第一个为空的代号),3就指向了con。就是说系统把1原来的指向复制给了3,目的是语句结束后能找回原来的指向,这就相当于备份。

第二步:现在3的指向是con。然而由于要运行“3>nul”,因此还要备份3的指向。此时4是空的,系统就把3的指向con复制给了4,即4现在指向con。就是说3以4为备份。

第三步:由于“3>nul”使得3指向了nul。

第四步:这行语句结束时,1要找回原来的指向,从以上叙述我们知道,3是1的备份,因此1要通过3来恢复“原来”的指向,但此时3的指向已经变为了nul,故1就指向nul。

第五步:而3要恢复原来的指向就要找4,4指向con,故3恢复为con;4原始指向是空的,其备份在5中,故4的指向恢复到空。

至此我们理顺一下,现在1指向nul,2指向默认值con,3指向con,4之后都是空指向。那么在运行后两句echo语句时由于1指向nul,即标准输出被重定向到空设备,故显示被屏蔽。

再来看看这句 “echo 这是怎么回事,难道就不能 1>con 4>con” 这句是怎么工作的呢?

第一步:1当前指向是nul,由于要运行“1>con”,因此要进行备份。但此时3指向的是con非空,故系统将1的指向备份到4,即4指向nul。

第二步:又由于要运行“4>con”,故4现在的指向nul就又被备份到5中,5以后的事姑且省略。
第三步:运行完“4>con”之后4就指向con。
第四步:该行程序结束后,1要通过4来恢复指向。4指向con,故1指向con从而恢复了默认状态。而4找5,5指向nul,故4指向nul。
我们再数一数现在的情况,0指向con,1指向con,2指向con,3没动还是指向con,4指向nul,5以后都为空指向。
会不会有点乱?那就再好好的看几遍吧,或者是看看这篇,讲的更基础一些:

第四节
我们已经知道“echo hero”相当于“echo hero 1>con 2>con”,con表示控制台,可以把con看做是特殊的文件,这就是我们无法建立名为con文件的原因。

再对“>”和“>>”的重定向机制做个分析。当要重定向到的文件有隐藏或系统属性时,“>>”可以正常运行,而 “>”就无法操作了。据此我推测,对于“>”的重定向输出,如果文件不存在当然是建立文件,而如果文件存在就先将文件删除,然后再新建文件,也就是说并非是覆盖文件的内容而是先删除文件再建立新文件。

通过第三节的讲解你应该明白为什么类似这样的语句“echo hero >nul >con >hero.txt >con”会以最后一个为准了吧。

最后需要注意一点的是--重定向输出无法输出到只读文件。

完。
WIN下的大部分重定向与Unix还是一致的,嗯

下面是补充

Windows下cmd标准输入输出重定向

Command 功能
command > filename 把标准输出重定向到一个文件中
command >> filename 把标准输出重定向到一个文件中(追加)
command 1 > fielname 把标准输出重定向到一个文件中
command > filename 2>&1 把标准输出和标准错误一起重定向到一个文件
command 2 > filename 把标准错误重定向到一个文件中
command 2 >> filename 把标准错误重定向到一个文件中(追加)
command >> filename 2>&1 把标准输出和标准错误一起重定向到一个文件中(追加)
command < filename1 > filename2 command命令以filename1文件作为标准输入,以filename2文件作为标准输出
command < filename command命令以filename文件作为标准输入
command << delimiter 从标准输入中读入,直至遇到delimiter分界符
command < &m 将文件描述符m作为标准输入
command > &m 将标准输出重定向到文件描述符m中
command < &- 关闭标准输入

以上就是Windows cmd命令行输入输出重定向问题的详细内容,更多关于cmd命令行输入输出重定向的资料请关注自学编程网其它相关文章!

编程技巧