我刚刚决定尝试使用 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
行为与zsh
在bash
.如果您确实认为您看到了不同的行为,请使用(a)您正在使用的版本zsh
和(b)问题的完整示例来更新您的问题,显示实际的目录内容和您的特定命令行重新使用。
答案2
通过缩小到 中的负责行.zshrc
,我可以自己弄清楚:
事实上,它比某种管道虚拟终端简单得多。该错误来自第 1477 行grml的配置看起来像这样:
alias ls='ls -b -CF '${ls_options:+"${ls_options[*]} "}
所以该ls
命令显然不是直接调用的,而是通过别名调用的。并且该选项通过该选项显式激活列输出-C
。