简体   繁体   English

为什么要命令; ls -l file_doesnot_exists > /dev/null 2>&1 正在工作; ls -l 2>&1 file_doesnot_exists > /dev/null 不是

[英]why the command; ls -l file_doesnot_exists > /dev/null 2>&1 is working while; ls -l 2>&1 file_doesnot_exists > /dev/null is not

I'm just wondring how to know which instruction we normally put first in a shell command?我只是想知道如何知道我们通常将哪个指令放在 shell 命令中? for example, why the command:例如,为什么命令:

ls -l file_doesnot_exists > /dev/null 2>&1

is working, while this command:正在工作,而此命令:

ls -l 2>&1 file_doesnot_exists > /dev/null

is not不是

Note:笔记:

  • The question is tagged linux , which means that ls is not a built-in alias of PowerShell's own Get-ChildItem cmdlet (which applies on Windows only) and instead refers to the standard /bin/ls Unix utility.问题标记为linux ,这意味着ls不是PowerShell 自己的Get-ChildItem cmdlet 的内置别名(仅适用于Windows ),而是指标准/bin/ls Z6EC1BD1EA6A5D62BDD63B 实用程序。

  • In PowerShell there is no difference between your commands, because the order of redirections does NOT matter .PowerShell中,您的命令之间没有区别,因为重定向顺序无关紧要

    • All targeted output streams always retain their identity: any redirection of a stream affects any other redirections to the same stream in the same command.所有目标output 流始终保留其身份: stream 的任何重定向都会影响到同一命令中相同 stream 的任何其他重定向。

    • Therefore, neither of your commands work as intended and produce no output , because while 2>&1 redirects the error stream ( 2 ) into the success output stream ( 1 ), the latter's output is ultimately discarded , due to > /dev/null ( > is the same as 1> ), including the redirected error-stream output. Therefore, neither of your commands work as intended and produce no output , because while 2>&1 redirects the error stream ( 2 ) into the success output stream ( 1 ), the latter's output is ultimately discarded , due to > /dev/null ( >1>相同),包括重定向的错误流 output。

  • By contrast, in POSIX-compatible shells such as Bash , the order of redirections DOES matter :相比之下,在与POSIX 兼容的 shell (例如 Bash )中,重定向的顺序确实很重要

    • ls -l 2>&1 file_doesnot_exists > /dev/null WORKS as intended: ls -l 2>&1 file_doesnot_exists > /dev/null预期工作:

      • 2>&1 redirects stderr output to the original stdout. 2>&1将标准错误 output 重定向到原始标准输出。
      • The later redirection of stdout ( > is the same as 1> ) has no effect on 2>&1后面的 stdout 重定向( >1>一样)对2>&1没有影响
      • The net effect is that only stderr lines print to stdout, while stdout lines are discarded (by the redirection to /dev/null ).最终效果是只有stderr行打印到 stdout,而 stdout 行被丢弃(通过重定向到/dev/null )。
    • By contrast, ls -l file_doesnot_exists > /dev/null 2>&1 DOES NOT and produces no output :相比之下, ls -l file_doesnot_exists > /dev/null 2>&1 DOES NOT并且不会产生output

      • > /dev/null redirects stdout to /dev/null , ie effectively discards stdout output. > /dev/null将标准输出重定向到/dev/null ,即有效地丢弃标准输出 output。

      • Because 2>&1 comes later in the command, 1 refers to the already redirected stdout, so that stderr output too is discarded.因为2>&1在命令后面出现,所以1指的是已经重定向的标准输出,所以标准错误 output 也被丢弃。

    • See this answer for more information.有关更多信息,请参阅此答案

Assuming this is being ran in PowerShell Core ( since the tags indicate it is ), it's safe to assume you're confusing bash commands with PowerShell cmdlets.假设这是在 PowerShell 核心中运行的(因为标签表明它是),假设您将 bash 命令与 PowerShell cmdlet 混淆是安全的。 In PowerShell, you have to be mindful of Terminating , and Non-Terminating errors.在 PowerShell 中,您必须注意TerminatingNon- Termying 错误。

Simply put, the reason why ls -l 2>&1 file_doesnot_exists > /dev/null doesn't work is because, ls - alias for Get-ChildItem - produces a terminating error that halts the rest of the execution since it is missing an argument.简而言之, ls -l 2>&1 file_doesnot_exists > /dev/null不起作用的原因是, ls - Get-ChildItem的别名- 产生一个终止错误,该错误会停止执行的 rest,因为它缺少参数. This is demonstrated in a Try {...} catch {...} statement where the catch block " catches " terminating errors.这在Try {...} catch {...}语句中得到了证明,其中catch块“捕获”终止错误。

try {
    ls -l
}
catch {
    "it no workie"
}

Since ls is an alias to Get-ChildItem , the - L parameter defaults to -LiteralPath where it's now expecting a path and it's erroring out when ran since it wasn't provided.由于lsGet-ChildItem的别名,因此L参数默认为-LiteralPath ,它现在需要一个路径,并且由于未提供它而在运行时出错。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM