Bash脚本find命令替换赋值变量时返回Permission denied的原因
问题根因
- 你看到的
Permission denied报错本质是find遍历到当前用户无读/执行权限的路径时,向stderr输出的标准提示,这个行为和你是否将find结果存入变量没有关联——两种写法下,只要find遍历到无权限路径都会输出这个提示。 - 之前的写法你没有感知到这个报错,是两个Bash运行规则共同导致的:
- 脚本头部的
-eu开启了set -e(errexit)模式:该模式下普通命令返回非0退出码时会直接终止脚本,但位于if/while/until条件判断内部的命令不受这个规则约束。你最初的find命令完全写在if判断条件内,哪怕find因为权限问题返回非0,脚本也不会异常退出,你大概率没注意到混杂在正常输出里的权限报错行。 - 最初的写法用管道连接
find和wc -l:Bash默认关闭pipefail选项时,整条管道的退出码只取最后一个命令(也就是wc -l)的退出码,只要wc正常完成统计就返回0,完全掩盖了前序find命令执行出错的事实。
- 脚本头部的
- 当你把find结果赋值给变量的语句写在if判断外的全局作用域时,find一旦因为权限问题返回非0退出码,
set -e就会立刻触发脚本终止,你看到脚本异常退出+Permission denied提示,才会误以为是新写法触发了权限问题。 - 额外注意:你之前用的
-not -path "./node_modules/*"只是过滤find最终输出的结果条目,不会阻止find进入node_modules目录遍历,如果node_modules下存在权限受限的路径,find依然会进入遍历并触发报错。
优化写法
如果要实现“查找空文件+复用结果+避免无意义报错”的需求,可以参考下面的实现:
#!/bin/bash -eu # 1. 用-prune参数直接跳过node_modules目录,根本不进入遍历,从源头减少权限报错 # 2. 用数组存储文件列表,避免文件名包含空格、换行时出现解析错误 # 3. 不需要多次执行find,性能更好 mapfile -t empty_file_list < <(find . -path "./node_modules" -prune -o -type f -empty -print) if [[ ${#empty_file_list[@]} -gt 0 ]]; then echo "[check-for-empty-files] Empty files found:" printf '%s\n' "${empty_file_list[@]}" exit 1 else echo "[check-for-empty-files] No empties." fi
如果不需要显示find遍历过程中的权限类提示,可以在find命令末尾加上2>/dev/null把stderr重定向到空设备即可。
内容的提问来源于stack exchange,提问作者Curtis
相关产品推荐
相关产品推荐

