为什么需要 xargs?

see*_*ker 31 bash xargs pipe coreutils

假设我想删除目录中除名为“notes.txt”的文件之外的所有文件。我会用管道来做到这一点,ls | grep -v "notes.txt" | xargs rm. 如果第二个管道的输出是 rm 应该使用的输入,为什么我需要 xargs?

为了进行比较,管道echo "#include <knowledge.h>" | cat > foo.c将回显的文本插入到文件中,而不使用 xargs。这两个管道有什么区别?

Gor*_*son 44

您混淆了两种截然不同的输入:标准输入和参数。参数是在命令开始时提供给命令的字符串列表,通常通过在命令名称之后指定它们(例如echo these are some argumentsrm file1 file2)。另一方面,STDIN 是命令可以(可选)在启动后读取的字节流(有时是文本,有时不是)。以下是一些示例(请注意,cat可以采用参数或标准输入,但对它们执行不同的操作):

echo file1 file2 | cat    # Prints "file1 file2", since that's the stream of
                          # bytes that echo passed to cat's STDIN
cat file1 file2    # Prints the CONTENTS of file1 and file2
echo file1 file2 | rm    # Prints an error message, since rm expects arguments
                         # and doesn't read from STDIN
Run Code Online (Sandbox Code Playgroud)

xargs 可以认为是将 STDIN 样式的输入转换为参数:

echo file1 file2 | cat    # Prints "file1 file2"
echo file1 file2 | xargs cat    # Prints the CONTENTS of file1 and file2
Run Code Online (Sandbox Code Playgroud)

echo 实际上或多或少相反:它将其参数转换为 STDOUT(可以通过管道传输到其他命令的 STDIN):

echo file1 file2 | echo    # Prints a blank line, since echo doesn't read from STDIN
echo file1 file2 | xargs echo    # Prints "file1 file2" -- the first echo turns
                                 # them from arguments into STDOUT, xargs turns
                                 # them back into arguments, and the second echo
                                 # turns them back into STDOUT
echo file1 file2 | xargs echo | xargs echo | xargs echo | xargs echo    # Similar,
                                 # except that it converts back and forth between
                                 # args and STDOUT several times before finally
                                 # printing "file1 file2" to STDOUT.
Run Code Online (Sandbox Code Playgroud)


Ale*_* P. 10

cat接受STDINrm不接受输入。对于此类命令,您需要逐行xargs迭代STDIN并使用命令行参数执行命令。