管道时何时使用 xargs?
When to use xargs when piping?
我是 bash 的新手,我正在尝试了解 xargs
的用法,这对我来说仍然不是很清楚。例如:
history | grep ls
这里我在我的历史记录中搜索命令ls
。在此命令中,我没有使用 xargs
,它运行良好。
find /etc - name "*.txt" | xargs ls -l
我这个,我不得不使用 xargs
但我仍然无法理解其中的区别,我无法正确决定何时使用 xargs
以及何时不使用。
xargs(1) 在 读取非 NUL 分隔输入.
时是危险的(已损坏、可利用等)
如果您使用的是文件名,请改用 find
的 -exec [command] {} +。
如果您可以获得以 NUL 分隔的输出,请使用 xargs -0
.
简短回答:暂时避免xargs
。 Return 到 xargs
当您编写了数十个或数百个脚本时。
命令可以从参数中获取输入(比如rm bad_example
)或者可以从stdin
中获取输入(不仅是rm -i is_this_bad_too
之后的y,还有read answer
).其他命令如 grep
和 sed
将查找参数,当参数不显示输入时,切换到输入。
您的 grep
示例可以很好地从标准输入读取,不需要什么特别的东西。
您的 ls
需要 find 的输出作为参数。 xargs
只是扭转局面的一种方式。使用 man xargs
了解更多关于 xargs 的信息。备选方案:
find /etc -name "*.txt" -exec ls -l {} \;
find /etc -name "*.txt" -ls
ls -l $(find /etc -name "*.txt" )
ls /etc/*.txt
当你在 /etc 中有 a nasty filename with spaces.txt
时,首先尝试看看哪个命令是最好的。
GNU Parallel 可以做与 xargs 相同的事情,但没有损坏和可利用的 "features"。
您可以通过查看示例来学习 GNU Parallel http://www.gnu.org/software/parallel/man.html#EXAMPLE:-Working-as-xargs--n1.-Argument-appending and walking through the tutorial http://www.gnu.org/software/parallel/parallel_tutorial.html
xargs
可以在需要从一个命令获取输出并将其用作另一个命令的参数时使用。在您的第一个示例中, grep
从标准输入中获取数据,而不是作为参数。所以,不需要xargs
。
xargs
从标准输入中获取数据并执行命令。默认情况下,数据作为参数附加到命令的末尾。但是,它可以插入任何地方,使用占位符作为输入。传统的占位符是{}
;使用它,您的示例命令可能会写成:
find /etc -name "*.txt" | xargs -I {} ls -l {}
如果 /etc
中有 3 个文本文件,您将获得每个文件的完整目录列表。当然,你可以直接写 ls -l /etc/*.txt
省去麻烦。
另一个示例让您重命名这些文件,并要求占位符 {}
使用两次。
find /etc -name "*.txt" | xargs -I {} mv {} {}.bak
这些都是不好的例子,一旦你有一个包含空格的文件名就会崩溃。您可以通过告诉 find
用空字符分隔文件名来解决这个问题。
find /etc -print0 -name "*.txt" | xargs -I {} -0 mv {} {}.bak
我个人的看法是,几乎总有使用 xargs
的替代方法(例如 find
的 -exec
参数),学习这些方法会更好。
当您使用不带 xargs
的管道时,实际数据将输入到下一个命令中。另一方面,当使用带有 xargs
的管道时,实际数据被视为下一个命令的参数。举一个具体的例子,假设您有一个包含 a.txt
和 b.txt
的文件夹。 a.txt
只包含一行 'hello world!',而 b.txt
只是空行。
如果你这样做
ls | grep txt
你最终会得到输出:
a.txt
b.txt
然而,如果你这样做
ls | xargs grep txt
你什么也得不到,因为文件 a.txt 和 b.txt 都不包含单词 txt.
如果命令是
ls | xargs grep hello
你会得到:
hello world!
那是因为 xargs
,ls
给出的两个文件名作为参数传递给 grep
,而不是实际内容。
我是 bash 的新手,我正在尝试了解 xargs
的用法,这对我来说仍然不是很清楚。例如:
history | grep ls
这里我在我的历史记录中搜索命令ls
。在此命令中,我没有使用 xargs
,它运行良好。
find /etc - name "*.txt" | xargs ls -l
我这个,我不得不使用 xargs
但我仍然无法理解其中的区别,我无法正确决定何时使用 xargs
以及何时不使用。
xargs(1) 在 读取非 NUL 分隔输入.
时是危险的(已损坏、可利用等)如果您使用的是文件名,请改用 find
的 -exec [command] {} +。
如果您可以获得以 NUL 分隔的输出,请使用 xargs -0
.
简短回答:暂时避免xargs
。 Return 到 xargs
当您编写了数十个或数百个脚本时。
命令可以从参数中获取输入(比如rm bad_example
)或者可以从stdin
中获取输入(不仅是rm -i is_this_bad_too
之后的y,还有read answer
).其他命令如 grep
和 sed
将查找参数,当参数不显示输入时,切换到输入。
您的 grep
示例可以很好地从标准输入读取,不需要什么特别的东西。
您的 ls
需要 find 的输出作为参数。 xargs
只是扭转局面的一种方式。使用 man xargs
了解更多关于 xargs 的信息。备选方案:
find /etc -name "*.txt" -exec ls -l {} \;
find /etc -name "*.txt" -ls
ls -l $(find /etc -name "*.txt" )
ls /etc/*.txt
当你在 /etc 中有 a nasty filename with spaces.txt
时,首先尝试看看哪个命令是最好的。
GNU Parallel 可以做与 xargs 相同的事情,但没有损坏和可利用的 "features"。
您可以通过查看示例来学习 GNU Parallel http://www.gnu.org/software/parallel/man.html#EXAMPLE:-Working-as-xargs--n1.-Argument-appending and walking through the tutorial http://www.gnu.org/software/parallel/parallel_tutorial.html
xargs
可以在需要从一个命令获取输出并将其用作另一个命令的参数时使用。在您的第一个示例中, grep
从标准输入中获取数据,而不是作为参数。所以,不需要xargs
。
xargs
从标准输入中获取数据并执行命令。默认情况下,数据作为参数附加到命令的末尾。但是,它可以插入任何地方,使用占位符作为输入。传统的占位符是{}
;使用它,您的示例命令可能会写成:
find /etc -name "*.txt" | xargs -I {} ls -l {}
如果 /etc
中有 3 个文本文件,您将获得每个文件的完整目录列表。当然,你可以直接写 ls -l /etc/*.txt
省去麻烦。
另一个示例让您重命名这些文件,并要求占位符 {}
使用两次。
find /etc -name "*.txt" | xargs -I {} mv {} {}.bak
这些都是不好的例子,一旦你有一个包含空格的文件名就会崩溃。您可以通过告诉 find
用空字符分隔文件名来解决这个问题。
find /etc -print0 -name "*.txt" | xargs -I {} -0 mv {} {}.bak
我个人的看法是,几乎总有使用 xargs
的替代方法(例如 find
的 -exec
参数),学习这些方法会更好。
当您使用不带 xargs
的管道时,实际数据将输入到下一个命令中。另一方面,当使用带有 xargs
的管道时,实际数据被视为下一个命令的参数。举一个具体的例子,假设您有一个包含 a.txt
和 b.txt
的文件夹。 a.txt
只包含一行 'hello world!',而 b.txt
只是空行。
如果你这样做
ls | grep txt
你最终会得到输出:
a.txt
b.txt
然而,如果你这样做
ls | xargs grep txt
你什么也得不到,因为文件 a.txt 和 b.txt 都不包含单词 txt.
如果命令是
ls | xargs grep hello
你会得到:
hello world!
那是因为 xargs
,ls
给出的两个文件名作为参数传递给 grep
,而不是实际内容。