我只是想知道如何知道我们通常首先在 shell 命令中放置哪个指令? 例如 为什么命令:
ls -l file_doesnot_exists > /dev/null 2>&1
正在工作,而此命令:
ls -l 2>&1 file_doesnot_exists > /dev/null
莫
注意:
- 该问题被标记为
linux
,这意味着ls
不是PowerShell自己的Get-ChildItem
cmdlet(仅适用于Windows)的内置别名,而是指标准的/bin/ls
Unix实用程序。
-
在PowerShell中,命令之间没有区别,因为重定向的顺序无关紧要。
-
所有目标输出流始终保留其标识:流的任何重定向都会影响同一命令中到同一流的任何其他重定向。
-
因此,您的两个命令都没有按预期工作并且不产生任何输出,因为当
2>&1
将错误流 (2
) 重定向到成功输出流 (1
时,后者的输出最终被丢弃,由于> /dev/null
(>
与1>
相同),包括重定向的错误流输出。
-
-
相比之下,在POSIX 兼容的 shell(如 Bash)中,重定向的顺序确实很重要:
-
ls -l 2>&1 file_doesnot_exists > /dev/null
按预期工作:2>&1
将标准输出重定向到原始标准输出。-
stdout的后续重定向(
>
与1>
相同)对2>&1
没有影响 - 净效果是只有标准输出行打印到 stdout,而标准输出行被丢弃(通过重定向到
/dev/null
)。
-
相比之下,
ls -l file_doesnot_exists > /dev/null 2>&1
不会产生任何输出:-
> /dev/null
将标准输出重定向到/dev/null
,即有效地丢弃标准输出输出。 -
由于命令后面出现
2>&1
,因此1
引用已重定向的 stdout,因此 stderr 输出也会被丢弃。
-
-
有关详细信息,请参阅此答案。
-
假设这是在PowerShell Core中运行的(因为标记表明它是),可以安全地假设你将bash命令与PowerShell cmdlet混淆。在 PowerShell 中,必须注意"终止"和"非终止"错误。
简而言之,ls -l 2>&1 file_doesnot_exists > /dev/null
不起作用的原因是,ls
(Get-ChildItem
的别名)会产生一个终止错误,该错误会停止执行的其余部分,因为它缺少参数。这在Try {...} catch {...}
语句中得到了证明,其中catch
块">捕获"终止错误。
try {
ls -l
}
catch {
"it no workie"
}
由于ls
是Get-ChildItem
的别名,因此 -L
参数默认-LiteralPath
它现在需要路径的位置,并且在运行时出错,因为它没有提供。