做什么
读 stdin,作为参数喂给指定命令。是管道里常被忽略的强工具。
痛点
# ❌ rm 不读 stdin,下面没用
find . -name "*.tmp" | rm
# ✓ xargs 把 stdin 转参数
find . -name "*.tmp" | xargs rm
常用参数
| 参数 | 含义 |
|---|---|
-n N |
每次喂 N 个参数 |
-I {} |
用 {} 占位,把输入逐个替换 |
-0 |
输入用 null 分隔(配 find -print0) |
-P N |
并行 N 个进程 |
-t |
显示要执行的命令(调试) |
-p |
每条问确认 |
实战
基础
find . -name "*.log" | xargs rm # 删所有 .log
find . -name "*.tmp" | xargs -p rm # 删前问
echo "1 2 3" | xargs # 把多行 → 一行:1 2 3
echo "1 2 3 4" | xargs -n 2 # 每行 2 个
# 1 2
# 3 4
含空格 / 特殊字符(安全姿势)
# ❌ 文件名带空格会乱
find . -name "*.log" | xargs rm
# ✓ 用 null 分隔
find . -name "*.log" -print0 | xargs -0 rm
占位符(精确控制位置)
# 给每个文件改名
find . -name "*.jpeg" | xargs -I {} mv {} {}.new
# 等同:mv file1.jpeg file1.jpeg.new ...
# 复制到多个目录
echo "/tmp /backup /elsewhere" | xargs -n 1 cp -r mydata
并行(加速)
# 4 个并行 gzip
find . -name "*.log" | xargs -P 4 -n 1 gzip
# 并行 ping
cat hosts.txt | xargs -P 10 -n 1 ping -c 1 -W 1
跟 -exec 的对比
find . -name "*.log" -exec rm {} \; # 每个 fork 一次,慢
find . -name "*.log" -exec rm {} + # 批量,快
find . -name "*.log" -print0 | xargs -0 rm # 批量,快(和上面差不多)
-exec ... + 和 xargs 效果近似——选哪个看习惯。含空格文件名永远 -print0 + -0。
坑
- 默认空白分隔——含空格 / 换行的文件名要
-print0+-0 - xargs 默认会把所有输入塞一条命令——会撑爆
ARG_MAX,加-n N限制 - 跟
cd等 shell 内置不工作——cd 在 xargs 起的子 shell 没意义