linux - 光盘 && ls | grep : How to execute a command in the current shell and pass the output

标签 linux bash unix

我创建了一个别名,以免每次我移动到一个新目录时都写 ls:

alias cl='cd_(){ cd "$@" && ls; }; cd_'

假设我有一个名为“下载”的文件夹(我当然碰巧有),所以我只需在终端中键入以下内容:

cl Downloads

现在我会在“下载”文件夹中找到自己,并收到文件夹中所有内容的列表,例如:example.txt、hack.hs、picture.jpg、...

如果我想移动到一个目录并查看是否有 hack.hs,我可以尝试这样的操作:

cl Downloads | grep hack

我得到的只是输出:

黑客.hs

但我将保留在原来的文件夹中(这意味着我不在下载中)。

我知道发生这种情况是因为每个命令都在子 shell 中执行,因此 cd Downloads && ls 在它自己的子 shell 中执行,然后输出(即我拥有的东西列表)通过管道重定向到 grep .这就是我不在新文件夹中的原因。

我的问题如下:

我该怎么做才能编写类似“cl Downloads | grep hack”的内容并获得“hack”-grep 列表并位于下载文件夹中?

非常感谢, 波尔


对于曾经用谷歌搜索这个的人: @gniourf_gniourf 提出了一个快速修复:

cl Downloads > >(grep hack)

有些人将此问题标记为可能与 Make bash alias that takes duplicates 重复,但我的 bash 别名已经采用参数这一事实表明情况并非如此。手头的问题是关于如何在当前 shell 中执行命令,同时将输出重定向到另一个命令。

最佳答案

如您所知(并在 BashFAQ #24 中介绍),原因

{ cd "$@" && ls; } | grep ...

...防止 cd 的结果在外壳中可见是因为 POSIX 不保证管道的任何组件在外壳中运行。 (一些 shell,包括 ksh [开箱即用] 和启用了非默认选项的非常现代的 bash,偶尔或可选地运行父 shell 中管道的最后一段,但这不能移植依赖上)。

一种适用于所有 POSIX shell 的避免这种情况的方法是将输出定向到命名管道,从而避免设置管道:

mkfifo mypipe
grep ... <mypipe &
{ cd "$@" && ls; } >mypipe

在现代 ksh 和 bash 中,有一个更短的语法可以为您完成此操作——如果操作系统提供了命名管道,则使用 /dev/fd 条目而不是设置命名管道:

{ cd "$@" && ls; } > >(grep ...)

在这种情况下,>(grep ...) 被替换为指向 FIFO 或 /dev/fd 条目的文件名,当写入时到有问题的进程,将输出重定向到 grep -- 但没有管道。


顺便说一句——我真的希望你以这种方式使用 ls 作为一个例子。 ls 的输出没有针对所有可能的文件名的范围明确指定,因此 grepping 它天生就不可靠。如果您确实想要构建流式结果,请考虑使用 printf '%s\0' * 在目录中发出一个以 NUL 分隔的非隐藏名称列表;或使用 glob expressions检查与特定模式匹配的文件(BashFAQ #4 涵盖了类似的场景); extglobs如果您需要比 POSIX 模式支持更接近完整的正则表达式匹配支持,则可用。

关于linux - 光盘 && ls | grep : How to execute a command in the current shell and pass the output,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38074882/

相关文章:

linux - 从主机网络浏览器访问驻留在 Docker 容器内的 apache2

python - 使用 Expect 在远程机器上运行本地 Python 脚本

linux - 用于查找与通配符匹配的文件总大小的简短命令

linux - 根据特定的搜索模式拆分文件,并使用 AWK 命令在拆分文件中包含特定行数

linux - 在 Shell 中,如何对作为字符串一部分的数字进行算术运算?

unix - 替换 sed 不更改文件

linux - 高内存架构

linux - 在 Bash 中循环文件的内容

linux - bash if 语句

linux - bash 脚本中的 source/etc/profile