【问题标题】:head doesn't work when piped a result from ls | grep从 ls | 传输结果时,head 不起作用grep
【发布时间】:2017-02-14 10:49:27
【问题描述】:

我正在尝试打印目录中所有文件的前 10 行。 目前,我正在使用:

ls -p | grep -v /

从 ls 的结果中删除所有目录,并仅返回目录中的文件。当我这样做时:

ls -p | grep -v / | head

我希望打印所有文件的前十行,但它不起作用。

有人可以帮忙吗?

【问题讨论】:

  • 如果命令没有按照您的预期执行,请阅读手册页!
  • @hek2mgl 显然,这是我做的第一件事
  • 你怎么能指望head 从标准输入读取文件名列表并打印其中的前 10 行?
  • @hek2mgl 我不经常使用 linux,所以我对它的了解不是很深,因此我寻求帮助。 Head 可以将多个文件作为参数,并将显示所有文件的前十行,因为 head file1 file2 file3 file4 将显示所有这些文件的前 10 行。知道了这一点,我认为将 ls 和 grep 的结果通过管道传输到 head 中,它的工作方式类似。显然我错了,但是头部手册页没有提供任何帮助
  • 好吧,当您不习惯 UNIX shell 环境时,可能真的很难获得。更频繁地使用 Linux! ;) 一件事,这就是反对票的原因。请在您的问题中更具体,it doesn't work 不具体。你需要解释什么不起作用。

标签: linux bash grep ls


【解决方案1】:

您的错误是假设命令从标准输入接收的是参数。不是。

当 head 从管道命令接收数据时,它接收的是数据流。 head 命令以与从作为参数传递的文件中读取的完全相同的方式读取该数据。可以这样想(这是伪代码,它不会起作用):

PSEUDO_PIPELINE <= ls -p | grep -v /  # Not valid shell syntax
head PSEUDO_PIPELINE                  # Not valid shell syntax

实际上有一种(有效的)方式来表达这一点,它被称为进程替换:

head <(ls -p | grep -v /)

这将获得与您观察到的完全相同(不需要的)结果,但更明显的是,管道前面的命令实际上是一个文件,而不是一个参数列表。

标准输入(以及输出流标准输出和标准错误)是每个命令从其启动上下文接收的内容。如果您愿意,它就像一个“隐藏参数”,并且进程可以与之交互(通过读取它直到到达文件末尾,因为它是一个特殊文件,但仍然是一个文件)。

现在你应该明白为什么你得到的是前面命令的前 10 10 行输出,而不是列出的每个文件的前 10 行。

你可以通过这样的方式实现你想要的:

find . -mindepth 1 -maxdepth 1 -type f -exec printf "\n%s ------\n" {} \; -exec head {} \;

这会找到每个文件,然后打印标题/分隔符行,以及每个文件的第一行。

【讨论】:

  • 感谢您的回复,这是一个很好的解释。您在底部提供的示例应该按原样工作吗?还是我需要更改某些内容以使其具体化?
  • @FlapJack 它应该按原样工作(它将使用当前目录中的文件)。如果您想删除标题/分隔符行并且只以连续方式打印文件内容,您可以通过删除从第一个 -exec 到第一个 \; 的部分来简化命令。
  • 是的,我试过了,但没有注意到 printf 之后的空格,所以它失败了。感谢您的帮助
【解决方案2】:

查找当前目录中所有非目录的文件:

find . -mindepth 1 -maxdepth 1 -type f

然后您可以使用-exec 对这些文件中的每一个运行命令。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-18
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    • 1970-01-01
    • 2017-04-07
    • 1970-01-01
    • 2017-07-31
    相关资源
    最近更新 更多