在Linux和Unix系统中,xargs命令是一个非常实用的工具,它可以将标准输入数据转换为命令行参数。通过使用xargs,我们可以更高效地在命令行中处理文件和数据。本文将详细介绍xargs命令的用法,并通过实例说明其应用场景。让我们一起来看看xargs的魅力吧!

一、xargs命令简介

xargs命令的作用是从标准输入构建和执行命令行,它可以从标准输入中读取数据,并将其作为命令行参数传递给其他命令。它可以处理文件、字符串列表或其他数据源,并将其转换为命令行参数,从而实现更灵活和高效的工作流。

二、xargs命令的基本用法

xargs命令的基本用法如下:


xargs [options] [command [initial-arguments]]

其中,[options]是可选的xargs选项,[command]是可选的要执行的命令,[initial-arguments]是可选的命令初始参数,未指定命令时,会将参数输出到标准输出。xargs会将标准输入数据转换为命令行参数,并传递给[command]执行。[command]收到的参数,将是[initial-arguments]和xargs传递的参数的并集。

三、xargs命令的常用选项

  • -0:处理空字符而非空格作为参数分隔符。
  • -a:从文件读取参数,而非标准输入。
  • -d:指定分隔符,缺省为空白符:空格、换行等。
  • -E:设置“文件结束符”。在处理标准输入时,如果遇到“文件结束符”,则其后的所有输入都将被忽略。
  • -i:参数替换,用从标准输入读取的参数替换initial-arguments中的内容{};如果需要指定非{},则使用-I(i的大写)选项指定。
  • -n:指定每个命令行参数的个数。
  • -P:指定并行执行的最大进程数。
  • -p:执行命令前提示用户确认。
  • -r:忽略无法执行的命令。
  • -s:限制命令及参数总字符数。
  • -t:在执行命令之前先打印命令。
  • -x:用于确保xargs在命令行长度(-s选项指定)超出限制时停止执行。

四、xargs命令示例

4.1 分段传递参数列表

xargs最显著的作用是将参数列表转换成小块分段传递给后续命令,以避免参数列表过长的问题。先看一个简单的示例:


~$ echo {1..10}|xargs
1 2 3 4 5 6 7 8 9 10

上例中xargs未使用任何选项和命令,对于少量参数,可一次性输出。但如果参数数量足够多,可能超过命令行允许的最大长度,xargs的作用就显示出来了。如下命令使用{1..50000}生成从1到50000的数字序列来模拟5万个参数,经xargs处理后,使用wc命令统计参数行数,之后使用cut命令截取每行参数查看前几个参数的内容:


~$ echo {1..50000}|xargs|wc -l 
3
~$ echo {1..50000}|xargs|cut -c 1-20
1 2 3 4 5 6 7 8 9 10
23696 23697 23698 23
45540 45541 45542 45

可以发现,参数已经分成了3块进行传递,因此结果有3行。

了解xargs的作用后,就可以应用到实际操作中。例如,删除某个目录下所有名称以.tmp结尾的文件,如果文件数量过多,使用rm *.tmp会收到“Arguments list too long”的错误提示。此时可以使用find命令找出需要删除的文件,然后使用xargs将文件列表分段传递给rm命令:


find . -name *.tmp | xargs rm -rf

此种情况可以用一个安全简单的方法进行模拟:创建一个目录tmp,该目录下仅一个名称为1的文件。使用{1..1000000}产生序列模拟名称为从1到1000000的文件名,然后执行命令进行模拟并查看结果:


~$ cd tmp
~/tmp$ ls
1
~/tmp$ ls {1..2}
ls: cannot access '2': No such file or directory
1
~/tmp$ ls {1..1000000}
-bash: /usr/bin/ls: Argument list too long
~/tmp$ echo {1..2}|xargs ls
ls: cannot access '2': No such file or directory
1
~/tmp$ echo {1..1000000}|xargs ls 2>/dev/null
1

上述最后一个命令,为避免出现大量“No such file or directory”提示,使用“2>/dev/null”将标准错误输出到空设备/dev/null。

4.2 限定参数列表大小

xargs会根据后续命令所需的参数,按需对参数列表分块,以匹配命令所需的参数列表。例如以下命令,使用printf每行输出2个格式化后的数值,根据格式字符串中占位符的数量,每个printf需要接收2个数字参数:


~$ echo {1..3}|xargs printf "%02d %02d\n"
01 02
03 00

细心的你已经发现,虽然参数列表匹配正确,但对于源参数个数不是2(printf格式串中占位符个数)的整数倍时,输出结果不符合预期。或者假设每行需要输出更多数值时,不希望编写很长的格式串。可以先对单个数值进行格式化,最后使用-n选项限定每行输出的数值个数。例如,每行输出10个数值:


~$ echo {1..21}|xargs printf "%02d\n"|xargs -n 10
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20
21

4.3 参数替换

前面的示例中,xargs后面的命令,参数位置都是在命令的最后。但如果参数在命令的中间某个位置,或者需要用参数值替换命令中的指定内容时,就需要使用参数替换。

例如,将某个目录中30天以前的文件移动到备份目录。mv指令(移动或重命名文件)的简单语法为:


mv SOURCE DEST

被移动的文件名需要放在SOURCE的位置,可使用以下命令:


find /path/to/dir -type f -mtime +30|xargs -i mv {} /path/to/bak

其中-type f表示查询的目标为文件,-mtime +30表示修改日期在30天以前;{}会在执行时替换为具体的参数值,一个{}仅使用一个参数值进行替换。

五、总结

xargs是一款强大的工具,它可以帮助我们在命令行中更高效地处理文件和数据。无论是将文件列表传递给其他命令,还是将字符串列表作为参数传递,xargs都能满足需求。熟练掌握xargs,可以让你在命令行工作中更加得心应手!