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

Pao*_*olo 25 bash pipe

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

$ command -r FILENAME
Run Code Online (Sandbox Code Playgroud)

假设这FILENAME是一个包含文件名列表的文件,因为它是使用ls > FILENAME.

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

$ ls | command -r

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

Usage: command -r FILENAME
error: -r option requires an argument
Run Code Online (Sandbox Code Playgroud)

我怎样才能获得想要的效果?

Gil*_*il' 40

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

  • 许多命令将其-视为特殊名称,这意味着从标准输入读取而不是打开文件。这是约定,不是义务。

    ls | command -r -
    
    Run Code Online (Sandbox Code Playgroud)
  • 许多 unix 变体提供/dev了指定标准描述符的特殊文件。如果/dev/stdin存在,打开并读取它相当于从标准输入读取;同样,/dev/fd/0如果它存在。

    ls | command -r /dev/stdin
    ls | command -r /dev/fd/0
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果你的shell是ksh、bash或zsh,你可以让shell处理分配一些文件描述符的业务。这种方法的主要优点是它不依赖于标准输入,因此您可以将标准输入用于其他用途,并且您可以多次使用它。

    command -r <(ls)
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果命令希望名称具有特定形式(通常是特定扩展名),您可以尝试使用符号链接来欺骗它。

    ln -s /dev/fd/0 list.foo
    ls | command -r list.foo
    
    Run Code Online (Sandbox Code Playgroud)

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

    mkfifo list.foo
    ls >list.foo &
    command -r list.foo
    
    Run Code Online (Sandbox Code Playgroud)

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


ghm*_*014 7

它应该是:

ls | xargs -n 1 command -r
Run Code Online (Sandbox Code Playgroud)

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

ls | xargs -d '\n' -n 1 command -r
Run Code Online (Sandbox Code Playgroud)