【问题标题】:Command output redirection using pipe character使用管道字符的命令输出重定向
【发布时间】:2016-06-25 16:37:14
【问题描述】:

我试图了解输出重定向到另一个命令的工作原理。

我知道如果第二个命令是 find 可以使用它,因为 find 的帮助文本明确说明了这一点。它也可以与 findstr 一起使用,尽管 findstr 的帮助文本没有说明这一点。

所以问题是:

我如何知道其他 Windows 命令 shell 命令接受来自另一个命令的输出?

我创建了一个命令行,我希望输出为“18:33”,但它不起作用

C:>time /T | set /P a= && echo %a%
%a%

C:>setlocal enabledelayedexpansion
C:>time /T | set /P a= && echo !a!
!a!

为什么这不能按预期工作?

请注意这里的重点是将时间读取到变量中。我只是看不出管道对 find 或 findstr 以外的任何东西有什么用处。

【问题讨论】:

    标签: batch-file command-line cmd


    【解决方案1】:

    几乎所有接受输入的命令也可以与管道一起使用。

    您的SET /P 示例也可以工作,但需要注意。
    我在这里不使用延迟扩展,因为它只会增加更多的复杂性。

    time /T | ( set /P var= && set var )
    

    括号在这里很重要,否则隐式顺序将是

    ( time /T | set /P var= ) && set var
    

    但这失败了,因为管道会为双方创建两个新的 cmd.exe 实例。
    在这两个任务结束后,这些实例将再次被删除。
    因此,只能访问由同一(新)实例内的管道创建的变量。

    在许多情况下,管道对于自动化一些简单的问题很有用,例如

    echo Y | del *
    

    更多关于管道和延迟扩展的信息SO:Why does delayed expansion fail when inside a piped block of code?

    【讨论】:

      【解决方案2】:

      简短的回答是因为 windows 搞砸了。

      没有充分的理由说明您的上述命令不起作用,这完全是微软的罪魁祸首。他们的软件经常不仅无法运行,而且实际上无法以完全荒谬的方式运行,并且没有任何错误消息提示可能出了什么问题,从而浪费了人们的时间。如果你想要一个体面的命令提示符,它通常可以工作,如果它不工作,通常是由于你的错误而不是它的错误,试试 Linux。

      话虽如此,windows 命令提示符下有几个可用的命令可以处理它们的标准输入; sort 命令是我想到的。试试type text.txt | sort 看看会发生什么。

      要回答您的问题“我怎么知道?”,答案是您无法知道,因为我认为没有处理标准输入的所有命令的完整列表。但是,一般来说,如果一个命令对输入文件进行操作,并且它要求将输入文件名指定为参数,并且如果该参数是可选的,那么假设如果省略该参数,则该命令是相当安全的将处理其标准输入。

      此外,通过指定con 作为输入文件名,可以欺骗接受输入文件名作为非可选参数的命令来使用标准输入。因此,例如,单独输入 type 是行不通的,但尝试 type con 看看会发生什么。

      【讨论】:

        【解决方案3】:

        从文件中读取数据的命令通常但并不总是支持从句柄 STDIN 中读取数据。管道字符| 将写入处理应用程序A 的STDOUT 的输出重定向到处理应用程序B 的STDIN。有关更多详细信息,请阅读有关Using command redirection operators 和SS64 的Microsoft 文章关于Redirection的文章。

        哪些控制台应用程序支持来自 STDIN 的输入是一个文档问题。只有少数随 Windows 安装的控制台应用程序支持来自 STDIN 的输入。但是有很多第三方控制台应用程序支持来自 STDIN 的输入。他们中的许多人没有在文档中明确解释输入也可以从 STDIN 中读取,而不仅仅是从指定为参数的输入文件中读取。但是,通过一次试验,总是可以很快找到对 STDIN 数据输入的支持。

        FINDFINDSTR 中也支持 STDIN 的标准 Windows 控制台应用程序是 例如 MORE 和 排序

        cmd.exe 的大多数标准 Windows 控制台应用程序和内部命令不处理文件的内容,因此不支持 STDIN。有关 Windows 标准命令的列表,请参阅Microsoft's command-line reference。但有关 Windows 标准命令行命令的更多详细信息,可以在SS64.com - A-Z index of the Windows CMD command line 链接的网页上找到。

        从一个应用程序的 STDOUT 重定向到另一个应用程序的 STDIN 经常与第三方控制台应用程序一起使用,因为其中许多支持来自 STDIN。每个编译器/脚本解释器都会将消息写入 STDOUT 并将致命错误消息写入 STDERR,这些消息会被许多 GUI 文本编辑器和 IDE 应用程序重定向,用于捕获、过滤和打印这些消息到程序员的 GUI 窗口。此重定向使用与 Windows 命令解释器提供的重定向运算符 >>>| 相同的机制完成。

        一般来说,所有支持键盘输入的控制台应用程序也支持来自 STDIN 的输入,这些输入是从输出或其他应用程序或文件重定向的。但与往常一样,也有例外,例如某些应用程序设计只接受直接来自键盘的输入,而不是来自句柄 STDIN 的输入,例如出于安全原因,例如应用程序或脚本不应该确认/输入某些内容,但是一个真正的人类用户通过键盘。


        SET命令用于为环境变量赋值,或将1个或多个环境变量的值输出到STDOUT,或计算算术表达式,或提示批处理用户输入从 STDIN 读取的字符串。此命令不是为读取文件或写入文件而设计的。

        但是仍然可以使用set /Pjeb 在他的回答中描述的特殊语法将应用程序的输出重定向到环境变量。但是这种方法很少使用,我认为原因是所需表达式的复杂性。

        但是,演示代码用于将当前时间分配给环境变量。很多时候,有一个命令参数或其他功能可以避免将文本重定向到命令或控制台应用程序的 STDIN。获取以当前时间为值的环境变量也是如此。

        有预定义的环境变量DATETIME。在命令提示符窗口set /? 中运行并阅读所有输出帮助页面。最后一页列出了批处理文件中经常需要的一些特殊环境变量,并附有说明,包括 DATETIME

        尝试一下

        echo Current date is %DATE% and current time is %TIME%
        

        请注意,%DATE%%TIME% 返回的日期和时间字符串的格式取决于 Windows 区域和语言设置(国家/地区)中的当前设置。因此,仅当批处理文件始终在日期/时间格式众所周知且不会更改的同一台计算机上执行时,才使用%DATE%%TIME%。否则最好使用wmic.exe OS get localdatetime。有关 Windows 上日期/时间使用的更多详细信息,请参阅Find out if file is older than 4 hours in Batch file 上的答案。

        FOR 命令可用于将应用程序输出的字符串分配给 1 个或多个环境变量。在命令提示符窗口for /? 中运行以获取有关此命令的帮助。使用 FOR 的方法最常用于将应用程序的输出或从文件读取的文本分配给环境变量。

        批处理文件示例:

        @echo off
        for /F %%I in ('time /T') do set "a=%%I"
        echo Time is %a%
        

        【讨论】:

        • 刚刚对原始问题添加了评论。我的观点不是将时间读取到变量中。我只是看不出管道对 find 或 findstr 以外的任何东西有什么用处。
        • @Mofi 我想你只是忘记了SET /P 命令,接受用户输入以及来自标准输入的输入
        • @jeb 没错。我从不使用set /P(提示方法)将文件或其他应用程序中的字符串分配给环境变量,因为我只是不想“滥用”一个功能,即使它是可能的.所以我真的忘记了这个方法。我也从不使用echo Y | del *,因为它仅适用于英文Windows,而使用del /Q * 独立于Windows 的语言。但是感谢您的评论在一个重要方面纠正了我的答案。
        猜你喜欢
        • 2014-12-11
        • 1970-01-01
        • 2013-12-21
        • 2013-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多