在命令选项中使用从管道读取而不是从文件读取的数据


18

根据人的定义,此命令从文件获取输入。

$ command -r FILENAME

假设该FILENAME文件包含使用生成的文件名列表ls > FILENAME

相反,我如何才能ls直接将结果直接输入命令?在我看来,这样的事情应该是可能的:

$ ls | command -r

但事实并非如此,的输出ls不会被挂钩为参数。输出:

Usage: command -r FILENAME
error: -r option requires an argument

我如何获得理想的效果?


与此相关的其他问题的更多答案:如何将字符串传递给需要文件的命令?
ilkkachu

Answers:


31

这取决于命令。一些从文件读取的命令希望该文件是常规文件,其大小事先已知,并且可以从任何位置读取并倒带。如果文件的内容是文件名列表,则这不太可能:那么该命令可能会包含一个管道,它将从头到尾依次读取。有几种方法可以通过管道将数据提供给需要文件名的命令。

  • 许多命令都被-视为特殊名称,意味着从标准输入中读取而不是打开文件。这是惯例,不是义务。

    ls | command -r -
  • 许多Unix变体提供/dev了指定标准描述符的特殊文件。如果/dev/stdin存在,则将其打开并从中读取等同于从标准输入中读取;同样,/dev/fd/0如果存在。

    ls | command -r /dev/stdin
    ls | command -r /dev/fd/0
  • 如果您的Shell是ksh,bash或zsh,则可以使Shell处理分配一些文件描述符的事务。此方法的主要优点是它不受标准输入的约束,因此您可以将标准输入用于其他用途,并且可以多次使用。

    command -r <(ls)
  • 如果该命令希望该名称具有特定形式(通常是特定扩展名),则可以尝试使用符号链接来使它愚弄。

    ln -s /dev/fd/0 list.foo
    ls | command -r list.foo

    或者,您可以使用命名管道。

    mkfifo list.foo
    ls >list.foo &
    command -r list.foo

请注意,使用生成文件列表ls是有问题的,因为ls当文件名包含不可打印的字符时,它们往往会破坏文件名。printf '%s\n' *更加可靠-它将按字面意义打印文件名中的每个字节。包含换行符的文件名仍然会引起麻烦,但是如果命令需要以换行符分隔的文件名列表,则这是不可避免的。


+1列举所有可能性。IMO流程替代是这种情况的正确答案。
glenn jackman 2011年

7

它应该是:

ls | xargs -n 1 command -r

编辑:对于带有空格的名称:

ls | xargs -d '\n' -n 1 command -r

如果command认为它一次拥有命令行上所需的所有文件名,则可能会出现问题。某些版本的xargs一次会给出command几个文件名(在我看来,为10)。看起来GNU xargs一次提供了所有功能。
Bruce Ediger

2

实际上,据我所知,唯一可靠的解决方案可以处理所有文件名,包括其中包含换行符的文件名:

find . -maxdepth 1 -print0 | xargs -n 1 -0 command -r

在这种情况下,文件名中唯一不允许的字符是空字符,无论如何文件名中都不允许。


1

许多命令接受-的“文件名”表示“使用标准输入”,但是这种约定远非通用。阅读手册页。


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.