为什么命令替换有效而管道无效

为什么命令替换有效而管道无效

我正在练习|管道传递输出。

首先,我basename尝试

$ basename -a $(ls test_directory/*) 

此行按预期工作,仅显示文件的名称,而不显示目录的名称。

但是当我尝试将输出传输lsbasename

$ ls test_directory/* | basename -a

错误信息在这里:

basename: missing operand
Try 'basename --help' for more information.

我发现将上一个命令的输出作为参数传递给下一个命令Unix 和 Linux在该答案之一提及:

  1. 通过 stdin 传递输入:

    ls | wc -l 
    

    这将计算 ls 输出中的行数

  2. 通过命令行参数传递输入:

    wc -l $(ls)
    

    这将计算 ls 打印的文件列表中的行数

我不明白“ 的输出ls”和“ 打印的文件ls”之间的区别。它们不是一回事吗?我想了解其中的区别。

我想了解为什么ls td/* | basename -a 没有起作用。

答案1

ls | wc -l为了解释和之间的区别wc -l $(ls)。我将举一个例子。

1.ls | wc -l

正如文章中所提到的,该命令将计算“ls”输出中的行数。

例如,我有一个~/Desktop/Practice/python包含 4 个 Python 脚本的目录。
现在,如果我使用上述命令,我将获得以下输出:

4

这意味着wc -l输出的计数ls返回了 4 个 Python 脚本,因此计数变为 4

2.wc -l $(ls)

再次如帖子所建议的那样,此命令将计算“ls”打印的文件列表中的行数。
因为在这种情况下,您将“ls”作为参数传递给命令

现在,如果我在同一目录中使用上述命令,我会得到以下输出:

12 palindrome1.py  
11 palindrome2.py
12 palindrome3.py
6 palindrome4.py
41 total

这表明wc -l这次计算了返回给它的每个单独的 Python 脚本中的行数ls

命令行参数和标准输入的区别

实际的区别在于命令的来源。命令可以使用“命令行参数”或“标准输入”来获取输入。因此,如何获取特定命令的输入取决于命令的开发人员。

管道将一个命令的标准输出作为标准输入传递给第二个命令。因此,如果第二个命令无法处理标准输入,它将抛出错误。但是,有些命令同时接受命令行参数和标准输入,如“wc”,但结果不同,因为wc处理标准输入和命令行参数的方式不同。

在你的情况下是这样的basename。如果你阅读 basename 的手册页:

NAME
       basename - strip directory and suffix from filenames

SYNOPSIS
       basename NAME [SUFFIX]
       basename OPTION... NAME...

DESCRIPTION
       Print NAME with any leading directory components removed.  If specified, also remove a trailing SUFFIX.

       Mandatory arguments to long options are mandatory for short options too.

       -a, --multiple
              support multiple arguments and treat each as a NAME

明确指定basename使用命令行参数作为输入。因此管道将不起作用。

如何使管道工作

作为由@bac0n 建议,要执行basenamewith 管道,您需要使用xargs

ls | xargs basename -a

这是因为xargs它采用标准输入并将其作为“命令行参数”传递给另一个命令。

答案2

我可以证明这一点的最简单的方法:

在此处输入图片描述

一些命令被设计用来接受stdin。 举cat个例子。 你可以将 previews 命令的输出通过管道传输到cat

$ echo hi | cat

有些命令只接受参数作为输入,例如echo。如果你运行:

$ ls | echo

它会将 的输出通过管道传输lsecho。但echo不会接收它。要使用,echo您必须为其提供一些参数:

$ echo "I'm an argument"

如果您需要将命令的输出用作其他命令的参数(例如,在它仅接受参数而不接受的情况下stdin),您有不同的选择。一种是使用命令替换:

$ echo $(ls)

在这种情况下ls将运行,然后的输出ls将作为参数传递给echo

也一样basename。您必须传递参数。

还有一些命令可以stdin同时接受参数和。例如cat。如果你将某些内容通过管道传递给cat它,它会将其打印出来。但是对于参数,除非你传递一个,否则它filename会将其内容打印出来。

相关内容