-exec 对每个匹配文件各执行一次命令,{} 是 find 自行替换的固定占位符,不可嵌入字符串或被 shell 解析;用 \; 表示逐个执行,+ 表示批量传参以减少 fork 开销,但要求目标命令支持多参数。

find 的 -exec 不是“执行一次命令”,而是对每个匹配文件**各执行一次命令**——这是它和 xargs 最本质的区别,也是误用的根源。
为什么 -exec 后面必须写 ; 或 +
; 表示“每找到一个文件,就启动一次命令”,比如:find /tmp -name "*.log" -exec rm {} ; 会为每个 .log 文件调用一次 rm。这安全但慢,尤其文件多时 fork 开销明显。
而 + 表示“尽可能把多个文件路径拼成一批传给命令”,类似 xargs 的行为:find /tmp -name "*.log" -exec gzip {} + 会变成 gzip a.log b.log c.log ——前提是目标命令支持多参数(gzip 支持,rm 也支持,但 iconv 默认不支持单次处理多个输入)。
{} 在 -exec 中不是变量,是固定占位符
它不能出现在引号里、不能做字符串拼接、不能被 $() 包裹——Shell 不会解析它,find 自己替换。常见错误:
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
- 写成
find . -name "*.txt" -exec echo "file: $({})" ;→ 报错,{}不是 shell 变量 - 写成
find . -name "*.txt" -exec cp {} /backup/{}.bak ;→ 实际执行的是cp a.txt /backup/a.txt.bak?不,{}只能单独出现,不能嵌入路径中 - 正确做法:用
sh -c子 shell 封装:find . -name "*.txt" -exec sh -c 'cp "$1" "/backup/$(basename "$1").bak"' sh {} ;
权限与路径安全:-exec 前先加 -type f 和引号
直接 find /var -name "*.conf" -exec chmod 644 {} ; 很危险——如果某次匹配到的是目录,chmod 644 会让它不可进入(丢失执行位)。应明确限定类型:
find /etc -type f -name "*.conf" -exec chmod 644 {} ;- 文件名含空格或换行?
-exec本身能安全处理,但如果你在子 shell 里用ls或echo,记得给{}加双引号:-exec sh -c 'echo "found: $1"' sh "{}" ; - 路径含特殊字符(如
&、;)?不用怕,{}是原样传递,不会被 shell 解析
替代方案:什么时候该用 -exec ... + 而不是 ;
当目标命令接受多个路径作为参数,且你希望减少进程创建次数时,优先用 +。典型场景:
- 批量压缩:
find logs/ -name "*.log" -exec gzip {} +(比;快 5–10 倍,百个文件起效果明显) - 批量删除(慎用):
find /tmp -mmin +60 -name "*.tmp" -exec rm {} +(注意:rm支持多参数,但-delete更简洁安全) - 不适用的情况:
iconv、sed -i、mv单文件重命名——这些命令一次只处理一个输入,强行用+会报错或行为异常
-exec 看似简单,真正踩坑的点都在“{} 怎么用”和“命令能不能吃多个参数”上。别图省事跳过 -type 限定,也别在没验证前就把 ; 换成 +。

















