Bash脚本排除指定文件路径出错,求问题排查与修正
问题分析与修正方案
核心错误点
- 内层循环重复处理:每个找到的文件路径都会遍历整个排除列表,导致非排除目录被多次判断,出现重复输出。比如
folderwithfile3会和排除列表的两个项分别对比,两次都不匹配,因此会输出两次veryLongCommand。 - 判断逻辑颠倒:当前代码中,匹配到排除目录时会输出目录路径,否则执行命令,但你的实际需求是跳过排除目录,仅对非排除目录执行目标命令。
- 变量未加引号:
[ $sanitized == $key ]中变量未用双引号包裹,若路径包含空格会触发语法错误;Bash中推荐用=而非==做字符串比较。 find结果遍历不安全:for i in $(find ...)会将路径按空格拆分,若文件名/路径含空格会导致错误,应使用零分隔符的方式处理特殊字符。
修正后的代码
exclusionFilePaths=('/home/newcoder/Desktop/project/folderwithfile1' '/home/newcoder/Desktop/project/folderwithfile2') # 用-print0和read -d ''处理含空格的路径,避免拆分错误 find ~+ -type f -name "fileWantToFind.php" -print0 | while IFS= read -r -d '' i; do sanitized="${i%/*}" # 标记当前目录是否在排除列表中 is_excluded=0 for key in "${exclusionFilePaths[@]}"; do if [ "$sanitized" = "$key" ]; then is_excluded=1 break # 匹配到排除项后直接跳出循环,减少冗余判断 fi done # 仅非排除目录执行目标命令 if [ "$is_excluded" -eq 0 ]; then echo "veryLongCommand" # 替换为你的实际命令 fi done
额外优化方案
方案1:用grep简化排除判断(去掉内层循环)
exclusionFilePaths=('/home/newcoder/Desktop/project/folderwithfile1' '/home/newcoder/Desktop/project/folderwithfile2') # 将排除列表转为换行格式,用于grep匹配 exclusion_list=$(printf "%s\n" "${exclusionFilePaths[@]}") find ~+ -type f -name "fileWantToFind.php" -print0 | while IFS= read -r -d '' i; do sanitized="${i%/*}" # -Fxq:固定字符串整行匹配,静默模式仅返回状态 if ! printf "%s\n" "$sanitized" | grep -Fxq -f <(printf "%s\n" "$exclusion_list"); then echo "veryLongCommand" fi done
方案2:直接在find中排除目录(效率更高)
不需要后续判断,直接让find跳过指定目录:
find ~+ -type f -name "fileWantToFind.php" \ -not -path "/home/newcoder/Desktop/project/folderwithfile1/*" \ -not -path "/home/newcoder/Desktop/project/folderwithfile2/*" | while IFS= read -r i; do sanitized="${i%/*}" echo "veryLongCommand" done
注:-path匹配需要加*,确保跳过目录下的所有文件。
内容的提问来源于stack exchange,提问作者NewCoder
相关产品推荐
相关产品推荐

