如何在Bash中用find删除匹配文件后,仅在找到时执行额外命令?
解决find子进程无法修改主脚本变量的问题
原脚本的核心问题很明确:-exec启动的bash是独立子进程,它里面修改的test变量只在自身进程范围内生效,主脚本完全读不到这个修改后的值——所以不管有没有删到文件,主脚本里的test始终是初始值1,自然不会触发后续的echo "it worked!"。
给你几个靠谱的解决思路:
方法一:用临时文件做标记(最稳妥,适配所有文件名)
利用子进程可以读写文件的特性,让find在删除文件后创建一个临时标记文件,主脚本通过检查标记是否存在,就能准确判断是否处理过目标文件:
# 创建临时标记文件的路径 marker=$(mktemp) # 先确保标记不存在,避免误判 rm -f "$marker" # 找到文件就删除,删除成功后创建标记 find /home/ -name 'file_name_to_find' -exec rm {} \; -exec touch "$marker" \; # 检查标记是否存在,存在则执行额外命令 if [ -f "$marker" ]; then echo "it worked!" # 用完清理标记文件 rm -f "$marker" fi
这里find的-exec是链式执行的:只有成功删除文件,才会执行touch "$marker",完全能精准反映是否有文件被处理。
方法二:先检查文件存在性,再批量删除
先通过find快速判断有没有匹配的文件,有就执行删除和额外命令:
# 用-quit选项,找到第一个匹配文件就退出,提升效率 if find /home/ -name 'file_name_to_find' -quit; then # 批量删除所有匹配文件 find /home/ -name 'file_name_to_find' -exec rm {} \; echo "it worked!" fi
这个方法会执行两次find,如果文件系统没有实时变动的话完全没问题,优点是逻辑简单易懂。
方法三:用数组存储匹配文件(适合无特殊字符的文件名)
如果你的目标文件名里没有空格、换行这类特殊字符,可以把所有匹配文件存入数组,通过数组长度判断是否有文件:
# 把找到的文件存入数组 files=($(find /home/ -name 'file_name_to_find')) # 数组长度大于0说明存在目标文件 if [ ${#files[@]} -gt 0 ]; then rm "${files[@]}" echo "it worked!" fi
注意:如果文件名包含空格、引号或换行符,这个方法会出错,所以优先考虑前两种方案。
另外提一句,原脚本里的[[${test} == '2']]有语法错误,括号和变量之间需要加空格,正确写法是[[ ${test} == '2' ]],不过这不是导致问题的核心原因。
内容的提问来源于stack exchange,提问作者Claud
相关产品推荐
相关产品推荐

