什么时候需要 xargs?

什么时候需要 xargs?

这个xargs命令总是让我感到困惑。有一般规则吗?

请考虑以下两个例子:

$ \ls | grep Cases | less

打印与“Cases”匹配的文件,但将命令更改为touch将需要xargs

$ \ls | grep Cases | touch
touch: missing file operand
Try `touch --help' for more information.

$ \ls | grep Cases | xargs touch

答案1

不同之处在于目标程序接受的数据。

如果您只使用管道,它会接收 STDIN(标准输入流)上的数据作为一堆原始数据,并且一次可以对一行进行排序。然而,有些程序不接受标准输入的命令,它们希望在命令的参数中拼写出来。例如,touch在命令行上将文件名作为参数,如下所示:touch file1.txt.

如果您有一个输出文件名的程序标准输出并想使用它们作为参数touch,您必须使用xargs它读取 STDIN 流数据并将每一行转换为命令的空格分隔的参数。

这两件事是等价的:

# touch file1.txt
# echo file1.txt | xargs touch

xargs除非您确切知道它在做什么以及为什么需要它,否则不要使用。通常情况下,有比使用xargs强制转换更好的方法来完成这项工作。转换过程也充满了潜在的陷阱,如转义和单词扩展等。

答案2

为了扩展已经提供的答案,xargs可以做一件很酷的事情,这在当今的多核和分布式计算领域变得越来越重要:它可以并行处理作业。

例如:

$ find . -type f -name '*.wav' -print0 |xargs -0 -P 3 -n 1 flac -V8

将同时使用三个进程对 *.wav => *.flac 进行编码 ( -P 3)。

答案3

当您在 stdin 上有一个文件路径列表并且想要对它们执行某些操作时,xargs 特别有用。例如:

$ git ls-files "*.tex" | xargs -n 1 sed -i "s/color/colour/g"

让我们逐步检查一下:

$ git ls-files "*.tex"
tex/ch1/intro.tex
tex/ch1/motivation.tex
....

换句话说,我们的输入是我们想要执行某些操作的路径列表。

要了解 xargs 对这些路径的作​​用,一个不错的技巧是echo在命令之前添加,如下所示:

$ git ls-files "*.tex" | xargs -n 1 echo sed -i "s/color/colour/g"
sed -i "s/color/colour/g" tex/ch1/intro.tex
sed -i "s/color/colour/g" tex/ch1/motivation.tex
....

-n 1参数将使 xargs 将每一行变成它自己的命令。该sed -i "s/color/colour/g"命令将替换指定文件中所有出现color的。colour

请注意,这仅在路径中没有任何空格的情况下才有效。如果这样做,您应该通过传递标志来使用以 null 结尾的路径作为 xargs 的输入-0。一个示例用法是:

$ git ls-files -z "*.tex" | xargs -0 -n 1 sed -i "s/color/colour/g"

其作用与我们上面描述的相同,但如果其中一个路径中有空格,也可以工作。

这适用于任何生成文件名作为输出的命令,例如findlocate。如果您碰巧在包含大量文件的 git 存储库中使用它,则使用它git grep -l而不是使用它可能会更有效git ls-files,如下所示:

$ git grep -l "color" "*.tex" | xargs -n 1 sed -i "s/color/colour/g"

git grep -l "color" "*.tex"命令将给出包含短语“color”的“*.tex”文件列表。

答案4

xargs在您的示例中,您根本不需要使用,因为find它将准确且安全地执行您想要执行的操作。

您想要使用的正是find

find -maxdepth 1 -name '*Cases*' -exec touch {} +

在这个例子中-maxdepth 1意味着只在当前目录中搜索,不深入到任何子目录;默认情况下,find 将查找所有子目录(这通常是您想要的),除非您使用 maxdepth 对其进行约束。是{}将在其位置替换的文件的名称,是+两个命令结束标记之一,另一个是;.它们之间的区别在于,;意味着一次对每个文件执行该命令,而+意味着一次对所有文件执行该命令。但请注意,您的 shell 可能会尝试解释;自身,因此您需要使用 或 对其进行\;转义';'。是的,find有很多这样的小烦恼,但它的力量足以弥补它。

两者一开始学习起来都很棘手findxargs为了帮助您学习,xargs请尝试使用-p--interactive选项,该选项将显示它将要执行的命令并提示您是否要运行它。

类似地,find您可以使用-ok代替 来-exec提示您是否要运行该命令。

不过,有时候,您find无法完成您想做的所有事情,这就是xargs出现的地方。该-exec命令只接受{}出现的一个实例,因此,如果您在使用 so 时出现错误,find -type f -exec cp {} {}.bak \;您可以这样做:find -type f -print0 | xargs -0 -l1 -IX cp X X.bak

您可以了解更多有关运行命令在里面GNU Findutils 手册

另外,我提到可以find安全地执行您想要的操作,因为当您处理文件时,您将遇到空格和其他字符,这将导致问题,xargs除非您使用-0or--null选项以及生成以空字符终止的输入项的内容的空白。

相关内容