Bash脚本多文件存在性判断if-elif语句语法错误排查与修正
问题分析与修正方案
你的脚本报错核心是不符合bash中[ ](test命令)的语法规则,再加上通配符展开的潜在隐患,具体问题点和修正方法如下:
核心错误点
[ ]内部不能直接用&&/||[是bash内置的test命令,它的参数必须遵循test的语法规范:逻辑与要用-a、逻辑或要用-o;而&&/||是shell层面的逻辑运算符,不能放在[ ]内部。否定条件的语法错误
你写的! -a ${subj}/${subj}*file2不符合语法:在[ ]中否定单个条件,应该写成! -e 文件路径(注意!和后续条件之间必须有空格);组合条件更推荐拆分多个[ ]用&&/||连接,避免优先级混乱。通配符展开的隐患
直接写${subj}/${subj}*file1如果匹配到多个文件,会被bash展开成多个参数,导致[ -a ... ]或[[ -e ... ]]因参数数量过多报错。-a选项已被弃用
bash中-a(检查文件存在)属于过时选项,推荐用-e(检查文件/目录存在)或-f(检查普通文件存在)替代。
修正后的脚本
方案1:用[[ ]]+文件存在检查函数(推荐,彻底解决通配符问题)
先定义函数检查是否存在匹配通配符的文件,再在循环中调用:
# 定义函数:检查是否存在匹配指定通配符的文件 has_matching_file() { local pattern="$1" # 开启nullglob:通配符无匹配时返回空数组,而非原字符串 shopt -s nullglob local matched_files=( "$pattern" ) shopt -u nullglob # 匹配到至少一个文件则返回成功(0) [[ ${#matched_files[@]} -gt 0 ]] } # 遍历子目录(如果目录名带空格,建议用下面的while循环替代) # while IFS= read -r subj; do for subj in $(cat sublist.txt); do if has_matching_file "${subj}/${subj}*file1" && has_matching_file "${subj}/${subj}*file2"; then # 同时存在file1和file2的执行逻辑 echo "处理${subj}: 存在file1和file2" elif has_matching_file "${subj}/${subj}*file1" && has_matching_file "${subj}/${subj}*file3"; then # 同时存在file1和file3的执行逻辑 echo "处理${subj}: 存在file1和file3" elif has_matching_file "${subj}/${subj}*file2" && has_matching_file "${subj}/${subj}*file3"; then # 同时存在file2和file3的执行逻辑 echo "处理${subj}: 存在file2和file3" elif has_matching_file "${subj}/${subj}*file1" && ! has_matching_file "${subj}/${subj}*file2" && ! has_matching_file "${subj}/${subj}*file3"; then # 仅存在file1的执行逻辑 echo "处理${subj}: 仅存在file1" elif has_matching_file "${subj}/${subj}*file2" && ! has_matching_file "${subj}/${subj}*file1" && ! has_matching_file "${subj}/${subj}*file3"; then # 仅存在file2的执行逻辑 echo "处理${subj}: 仅存在file2" else # 其他情况(仅file3或无目标文件) echo "处理${subj}: 仅存在file3或无目标文件" fi done # done < sublist.txt
方案2:拆分[ ]命令(适合单文件匹配场景)
如果确定每个通配符最多匹配一个文件,可直接拆分[ ]避免语法错误:
# 遍历子目录 for subj in $(cat sublist.txt); do if [ -e "${subj}/${subj}"*file1 ] && [ -e "${subj}/${subj}"*file2 ]; then echo "处理${subj}: 存在file1和file2" elif [ -e "${subj}/${subj}"*file1 ] && [ -e "${subj}/${subj}"*file3 ]; then echo "处理${subj}: 存在file1和file3" elif [ -e "${subj}/${subj}"*file2 ] && [ -e "${subj}/${subj}"*file3 ]; then echo "处理${subj}: 存在file2和file3" elif [ -e "${subj}/${subj}"*file1 ] && ! [ -e "${subj}/${subj}"*file2 ] && ! [ -e "${subj}/${subj}"*file3 ]; then echo "处理${subj}: 仅存在file1" elif [ -e "${subj}/${subj}"*file2 ] && ! [ -e "${subj}/${subj}"*file1 ] && ! [ -e "${subj}/${subj}"*file3 ]; then echo "处理${subj}: 仅存在file2" else echo "处理${subj}: 仅存在file3或无目标文件" fi done
额外提示
如果sublist.txt中包含带空格的目录名,$(cat sublist.txt)会按空格拆分导致错误,建议替换为while read循环(方案1中已注释示例)。
内容的提问来源于stack exchange,提问作者SStt1002
相关产品推荐
相关产品推荐

