为什么`sort <(ls -l)`起作用而`sort <(ls -l)`失效?


32

今天,我通过这篇文章学习了关于fifo的知识:提到了命名管道cat <(ls -l)

我使用进行了一些实验sort < (ls -l),弹出一个错误:

-bash: syntax error near unexpected token `('`

然后我发现我在命令中添加了多余的空间。

但是,为什么这个额外的命令会导致此失败呢?为什么重定向符号必须靠近(


应该注意的是,* nix shell基于空格将内容拆分,该空格创建了Alec提到的令牌。
小鸡

Answers:


45

因为不是<,而是<()完全不同的。这称为流程替换,它是某些外壳程序的功能,使您可以将一个流程的输出用作另一个流程的输入。

><运营商输出重定向到输入的文件。该<()运营商的命令(进程)的交易,而不是文件。当你跑步

sort < (ls)

您试图ls在子shell中运行命令(这是括号的意思),然后将该子shell作为输入文件传递给sort。但是,这是不可接受的语法,您会看到错误。


3
您的回答很好,但是then sort is attempting to read the subshell as its input file→这显然是错误的,因为Bash甚至不会解析语法。既ls没有sort运行,也没有实际运行。
sleblanc

1
@sebleblanc公平的观点,改写了答案,谢谢。
terdon

1
在这种情况下,没有子外壳。< (ls)在这里不是有效的令牌。
cuonglm

@cuonglm否,因为bash将其视为语法错误。我的观点是,(ls)它将ls在子shell中运行。
terdon

22

因为那就是它的本意。

<(...)in bash是进程替换的语法。它是从中的同一运算符复制而来的ksh

<()|&;是特殊的词法标记中bash被用于形成不同的组合特殊运算符。<<(<<<&...各有各的作用。<用于重定向。<file< file将从文件重定向输入。<'(file)'将从一个名为的文件中重定向输入(file),但它<(file)是一个不同的运算符,而不是重定向运算符。

< (file)<后面(file)。在这种情况下,在bash(file)是无效的。(...)在某些情况下可以作为单个令牌有效:

(sub shell)
func () {
  ...
}
var=(foo bar)

但不在

sort < (cmd)

fish外壳中,情况有所不同。In中fish(...)用于命令替换(等效于$(...)in bash)。并且<用于像Bourne一样的shell中的输入重定向。

所以在fish

sort <(echo file)

与以下内容相同:

sort < (echo file)

那是:

sort < file

但这与的bash流程替换完全不同。

yash外壳程序中,另一个POSIX外壳<(...)程序不是用于进程替换,而是用于进程重定向

在那里,

sort <(ls -l)

短缺:

sort 0<(ls -l)

是重定向运算符。它或多或少等于:

ls -l | sort

在中bash<(ls -l)会扩展为管道的路径,因此更像是:

ls -l | sort /dev/fd/0

在中zsh(...)作为globlob运算符((*.txt|*.png)将扩展到txtpng文件)和glob限定符(*(/)例如,扩展到目录文件)作为重载。

在中zsh,在:

sort < (ls -l)

(ls -l)将被视为全局限定符。该l水珠预选赛是要匹配的链接数,并预计之后的数l(如ls -ld ./*(l2)将列出与2个链接中的文件),所以这就是为什么你会得到一个zsh: number expected错误出现。

sort < (w)zsh: no matches found: (w)而是会给出一个错误,因为(w)匹配可写的空名称文件。

sort < (w|cat)本可以对当前目录中wand和/或cat文件的内容进行排序...


为什么sort < $(ls -l)会出现此错误:bash: $(ls -l): ambiguous redirect
Edward Torvalds 2015年

@edwardtorvalds,因为$(ls -l)扩展到多个单词。使用引号防止split + glob(sort < "$(echo file)")。请注意,这种行为或bash与POSIX sh 的行为不同之处在于,bash在非交互式时(即使调用时也是如此sh)也会在其中进行split + glob 。
斯特凡Chazelas

通过查看,ls -l | sort /dev/fd/0我可以说的输出ls -l存储在其中,/dev/fd/0并且sort命令读取该输出以提供所需的输出。我正在tail -f --retry /dev/fd/0监视该文件,但未得到任何输出。为什么?我如何读取该文件?
爱德华·托瓦尔兹

在鱼中,可以(foo | psub)用来实现输入过程的替代;尚无替代(ha)替代输出过程。
Zanchey
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.