Bash脚本中布尔表达式内通配符匹配任意扩展名失败的问题求助
嘿,我懂你遇到的麻烦了!你在[[ -f ]]的条件判断里用*来匹配任意扩展名,但发现这个通配符完全没起作用,对吧?我来帮你拆解问题原因,再给你几个靠谱的解决办法。
先看看你自己做的测试,这个现象很典型:
tom$ if [[ -f /foo/Sandbox/Master-Files/master-2.txt ]]; then echo "files found"; fi files found tom$ if [[ -f /foo/Sandbox/Master-Files/master-2.* ]]; then echo "files found"; fi # 这里没有任何输出,判断直接失败
问题到底出在哪?
[[是Bash的内置条件表达式结构,在[[ -f 路径 ]]这个判断里,路径里的通配符不会被Shell自动展开。-f选项要求的是一个具体的、真实存在的单个文件路径,而master-2.*在这里只是被当作一个字面意义的文件名——也就是Shell会去寻找一个叫master-2.*的文件,而不是匹配所有以master-2.开头的文件,所以判断自然会失败。
几个可行的解决办法
你有几种简单的方式来实现“检查是否存在同名(不管扩展名)的文件”这个需求:
方法1:用compgen命令检测匹配文件
compgen可以帮你生成符合通配符模式的文件列表,我们只需要看它有没有匹配结果就行:
if compgen -G "$MasterFilesDir/$filename_no_ext.*" > /dev/null; then # 存在匹配的主文件,什么都不用做 else echo "Deleting (proxy version) $file since master version was not found in $MasterFilesDir ..." rm -f "$file" fi
compgen -G会自动展开通配符,如果有匹配的文件就会输出内容,我们把输出重定向到/dev/null,只看命令的返回值:有匹配就返回0(成功),没匹配就返回1(失败)。
方法2:开启nullglob选项,用数组判断
先开启nullglob(这个选项会让没有匹配的通配符返回空数组,而不是保留原字符串),然后把匹配的文件放进数组,判断数组是否为空:
shopt -s nullglob master_files=("$MasterFilesDir/$filename_no_ext".*) shopt -u nullglob # 用完可以关闭,避免影响脚本其他逻辑 if [[ ${#master_files[@]} -eq 0 ]]; then echo "Deleting (proxy version) $file since master version was not found in $MasterFilesDir ..." rm -f "$file" fi
数组master_files里会包含所有匹配的主文件,${#master_files[@]}是数组的元素个数,等于0就说明没有找到对应的主文件。
方法3:用find命令(适合复杂场景)
如果你的目录结构更深,或者需要更灵活的匹配规则,find也能搞定:
if ! find "$MasterFilesDir" -maxdepth 1 -type f -name "$filename_no_ext.*" | grep -q .; then echo "Deleting (proxy version) $file since master version was not found in $MasterFilesDir ..." rm -f "$file" fi
-maxdepth 1确保只在当前目录查找,-type f限定只找文件,grep -q .用来判断find是否有输出——有输出就说明找到了对应的主文件。
修改后的完整脚本示例
这里用方法1来修改你的原脚本,最终版本是这样:
# Loop through files in Proxy Files folder for file in "$ProxyFilesDir"/*; do # Extract filename without extension filename_no_ext=$(basename "${file%.*}") # Check if a file with the same name exists in Master Files folder if ! compgen -G "$MasterFilesDir/$filename_no_ext.*" > /dev/null; then echo "Deleting (proxy version) $file since master version was not found in $MasterFilesDir ..." rm -f "$file" fi done
这样应该就能正确判断是否存在同名不同扩展名的主文件了,你可以试试!
备注:内容来源于stack exchange,提问作者Tom S

