即使使用 grml 的 zsh 配置通过管道传输到 grep,ls 也会输出多列

即使使用 grml 的 zsh 配置通过管道传输到 grep,ls 也会输出多列

我刚刚决定尝试使用 zsh 来对抗 Bash,并遇到了一些不方便的行为,我在网上找不到任何关于这些行为的信息:

如果您ls | grep foo在 Bash 中执行 a,则ls每行仅包含一个文件,以便grep仅输出匹配的文件。似乎在某个地方(因为我在配置中找不到任何内容,我认为它一定是 Bash 代码本身),该-1选项被传递给ls.
然而 zsh 并没有那么神奇:如果你ls在没有进一步选项的情况下传递给grep,它就会这样做,并且你还会得到结果,它恰好出现在与匹配相同的行上。

我在 zsh 中实现 Bash 行为的想法是检测ls输出是否会通过管道传输,grep并为这种情况定义别名之类的东西。但我不确定这如何以及是否可能。

更新:正如 larsks 在下面指出的那样,Bash 在这里没有做任何特殊的事情,ls如果输出没有到达终端,它实际上应该以这种方式工作。

尽管如此,这就是我身上发生的事情:

> ls
a  b  c  d  e  f  g  h

bash$ ls | grep b
b

zsh> ls | grep b
a  b  c  d  e  f  g  h

我已经能够在 Ubuntu 11.10 上使用 zsh 4.3.11 和 GNU coreutils 8.5 以及在 Debian Squeeze 机器上使用 zsh 4.3.10 重现这一点。

更新2:在进一步调查时,我发现此错误仅在以下情况下出现:grml.zshrc活跃。如果是通过管道传输的,那么那里肯定有一些东西可以打开输出终端。有人知道要寻找什么吗?

答案1

根据ls文档,此行为是该ls命令固有的:

`-1'
`--format=single-column'
     List one file per line.  This is the default for `ls' when standard
     output is not a terminal.

当使用 管道连接到另一个进程时|stdout不应该是 tty。 bash没有做任何特别的事情。

在我的所有测试中,zsh在 Linux 上使用版本 4.3.15,zsh在 OS X 上使用版本 4.3.11,其ls行为与zshbash.如果您确实认为您看到了不同的行为,请使用(a)您正在使用的版本zsh和(b)问题的完整示例来更新您的问题,显示实际的目录内容和您的特定命令行重新使用。

答案2

通过缩小到 中的负责行.zshrc,我可以自己弄清楚:

事实上,它比某种管道虚拟终端简单得多。该错误来自第 1477 行grml的配置看起来像这样:

alias ls='ls -b -CF '${ls_options:+"${ls_options[*]} "}

所以该ls命令显然不是直接调用的,而是通过别名调用的。并且该选项通过该选项显式激活列输出-C

相关内容