为什么需要 xargs?
xargs 的作用是构建和执行命令行。

find 命令的 -exec 选项虽然也能对找到的文件执行命令,但它有一个局限性:一次只能处理一个文件。
find . -name "*.log" -exec rm {} \;
这条命令会为每一个找到的 .log 文件都执行一次 rm 命令,如果找到了 1000 个文件,系统就需要调用 1000 次 rm 命令,这非常低效。
xargs 的出现就是为了解决这个问题,它会将 find 的输出结果(文件名列表)收集起来,然后一次性地、高效地传递给一个命令,让该命令一次处理多个文件。
find 命令简介
find 用于在目录树中搜索文件,并根据指定的条件(如文件名、类型、大小、修改时间等)执行操作。

基本语法:
find [路径] [表达式]
常用表达式:
| 表达式 | 作用 | 示例 |
|---|---|---|
-name |
按文件名搜索(支持通配符 , , []) |
find . -name "*.txt" |
-type |
按文件类型搜索 | find /var -type f (文件), find /dev -type c (字符设备) |
-size |
按文件大小搜索 | find . -size +10M (大于10MB), find . -size -1G (小于1GB) |
-mtime |
最后修改时间搜索 | find . -mtime -7 (7天内修改过), find . -mtime +30 (30天前修改过) |
-user / -group |
按文件所有者或所属组搜索 | find /home -user bob |
-perm |
按文件权限搜索 | find . -perm 755 |
-exec |
对找到的文件执行指定命令 | find . -name "*.tmp" -exec rm {} \; |
xargs 命令简介
xargs 的全称是 "eXtended ARGuments",它从标准输入读取数据,并将其转换为命令的参数列表,然后执行该命令。
基本语法:
[command] | xargs [options] [command]

常用选项:
| 选项 | 作用 |
|---|---|
-d |
指定定界符,默认是换行符和空格。 |
-n |
指定每次执行命令时最多使用多少个参数。 |
-I |
指定一个替换字符串,在命令中用 或自定义字符串(如)来代表从 find 传来的参数。 |
-0 |
与 find 的 -print0 配合使用,处理包含空格、换行符等特殊字符的文件名。 |
-P |
指定并行进程的数量,可以极大提高处理速度。 |
find 与 xargs 的黄金组合
我们来看如何将它们完美结合。
场景1:高效删除大量文件(最经典用法)
目标:删除当前目录及其子目录下所有 .tmp 文件。
低效方法(使用 -exec):
# 每找到一个文件,就执行一次 rm
find . -name "*.tmp" -exec rm {} \;
高效方法(使用 xargs):
# find 的输出通过管道 | 传给 xargs # xargs 将所有文件名收集起来,一次性传给 rm find . -name "*.tmp" | xargs rm
或者更明确的写法(推荐):
find . -name "*.tmp" -print0 | xargs -0 rm
解释:
find . -name "*.tmp" -print0:-print0会让find在输出每个文件名后输出一个\0(空字符),而不是默认的换行符,这是处理包含空格、引号等特殊字符文件名的最安全方式。xargs -0:-0告诉xargs以\0作为分隔符来读取输入,从而能正确解析这些特殊的文件名。
场景2:对找到的文件执行复杂命令
目标:查找所有 .jpg 文件,并用 convert 命令将它们转换为 .png 格式。
这里 -exec 的写法会非常繁琐,而 xargs 配合 -I 则非常清晰。
find . -type f -name "*.jpg" | xargs -I {} convert {} {}.png
解释:
find . -type f -name "*.jpg":查找所有.jpg文件。xargs -I {}:-I选项告诉xargs,从标准输入读取的每一行内容,都应该被替换到后面命令的 位置。convert {} {}.png:对于xargs传来的每一个文件名(photo1.jpg), 会被替换成它,最终执行的命令是convert photo1.jpg photo1.jpg.png。
场景3:限制每次执行的参数数量
目标:查找所有 .log 文件,但每次 rm 最多只删除 20 个。
find . -name "*.log" | xargs -n 20 rm
解释:
xargs -n 20:-n选项限制了xargs每次最多传递 20 个参数给rm,如果找到了 100 个.log文件,xargs会分 5 次调用rm命令,每次处理 20 个文件,这在某些命令对参数长度有限制时非常有用。
场景4:并行处理,大幅提升速度
目标:查找所有 .mp4 文件,并用 ffmpeg 进行转码,利用多核CPU加速。
# -P 4 表示使用 4 个并行进程
find . -name "*.mp4" | xargs -P 4 -I {} ffmpeg -i {} -c:v libx265 {}.mkv
解释:
xargs -P 4:-P选项启动了 4 个并行的子进程。xargs会将任务列表分发给这些进程,同时处理,对于 CPU 密集型任务(如视频转码、压缩),这能极大地缩短总处理时间。
find -exec vs. find | xargs
这是一个常见的选择题,下面是它们的详细对比。
| 特性 | find ... -exec | find ... | xargs |
| :--- | :--- | :--- |
| 效率 | 较低,每找到一个文件就执行一次命令。 | 很高,将多个文件名打包,一次性执行命令。 |
| 灵活性 | 一般,命令结构固定,参数传递方式单一。 | 非常灵活,可以轻松构建复杂的命令行,配合 -I, -n, -P 等选项。 |
| 安全性 | 默认安全。 | 默认下,如果文件名包含空格或特殊字符,可能会出错。必须使用 -print0 和 -0 来保证绝对安全。 |
| 参数长度 | 受到系统 ARG_MAX 限制,但 -exec ... + 可以缓解。 | 同样受 ARG_MAX 限制,但 -n 选项可以轻松控制。 |
| 语法 | find . -name "*.log" -exec rm {} \; | find . -name "*.log" -print0 \| xargs -0 rm |
| 并行处理 | 不支持原生并行。 | 支持,通过 -P 选项可以轻松实现并行。 |
find -exec ... +
值得一提的是,find 的 -exec 选项本身也有一个更高效的用法,就是用 替代 \;。
# 高效的 -exec 用法
find . -name "*.log" -exec rm {} +
这个 的作用和 xargs 类似,它会将找到的所有文件名作为参数一次性传递给 rm 命令。find -exec ... + 在效率上和 xargs 是相当的,并且更简洁。
那么为什么还需要 xargs 呢?
因为 xargs 提供了 find -exec 无法实现的功能,尤其是:
- 更灵活的参数替换:
-I {}选项比-exec的 更强大。 - 并行处理:
-P选项。 - 控制每次的参数数量:
-n选项。 - 与任何能输出到标准流的命令结合:不仅仅是
find,grep,cat等都可以通过管道把数据传给xargs。
总结与最佳实践
-
首选
find -exec ... +:如果你的需求只是简单地对找到的文件执行一个命令,并且不涉及复杂参数处理或并行,find ... -exec command {} +是最简洁、高效且安全的选择。 -
需要复杂处理?用
xargs:当你需要-I(灵活替换)、-n(控制参数数量)、-P(并行)这些功能时,xargs是不二之选。 -
安全第一:只要文件名可能包含空格、换行符等特殊字符,强烈建议使用
find -print0 | xargs -0的组合,这是最安全、最健壮的用法。 -
利用并行:对于视频处理、压缩等耗时任务,大胆使用
xargs -P,可以显著提升处理速度。
掌握 find 和 xargs 的组合使用,是提升 Linux/Unix 命令行操作效率的关键一步。
