如何在Shell脚本中检查同名前缀文件及解决参数过多报错
解决Shell脚本检查同名前缀文件时的"[: too many arguments"警告
这个问题我碰到过不少次,本质是Shell通配符的展开特性导致的,咱们先搞清楚为什么会出现这个警告,再给你几个靠谱的解决方案。
问题原因
当你在脚本里写if [ ! -e MY_REPORT_*.txt ]时,如果当前目录存在多个匹配的文件(比如你提到的MY_REPORT_2018_04_23_01.txt、MY_REPORT_2018_04_23_02.txt),Shell会自动把通配符*展开成所有匹配的文件名。这时候你的条件判断就变成了:
if [ ! -e MY_REPORT_2018_04_23_01.txt MY_REPORT_2018_04_23_02.txt ]
而[(也就是test命令)的-e选项只能接受单个文件路径,一下子收到多个参数自然就会抛出"[: too many arguments"的警告了。
解决方案
方法1:用数组+nullglob选项(最推荐,处理特殊文件名也可靠)
这种方法利用Shell数组来存储匹配的文件,通过判断数组长度来确定是否存在目标文件:
# 开启nullglob选项:当通配符无匹配时,展开为空字符串而非保留原模式 shopt -s nullglob # 将所有匹配的文件存入数组 report_files=(MY_REPORT_*.txt) # 检查数组是否为空(即无匹配文件) if [ ${#report_files[@]} -eq 0 ]; then echo "files not present in current directory" exit 1 fi # 可选:关闭nullglob,恢复Shell默认行为 shopt -u nullglob
${#report_files[@]}表示数组的元素个数,为0就说明没有找到任何匹配的文件。
方法2:用ls命令做简单判断(适合基础场景)
如果你的文件名不会包含换行、空格这类特殊字符,可以用ls的返回状态来判断:
# 把ls的输出和错误都重定向到/dev/null,避免冗余输出 if ! ls MY_REPORT_*.txt >/dev/null 2>&1; then echo "files not present in current directory" exit 1 fi
ls命令在找不到匹配文件时会返回非0的状态码,!取反后就会触发后续的提示和退出操作。
方法3:用find命令(适合需要递归查找的场景)
如果需要递归查找子目录里的目标文件,或者更灵活的匹配规则,可以用find:
# -maxdepth 1 限制只在当前目录查找,不递归子目录;-type f 指定只找普通文件 if ! find . -maxdepth 1 -type f -name "MY_REPORT_*.txt" | grep -q .; then echo "files not present in current directory" exit 1 fi
grep -q .用来检查find是否有输出,-q表示静默模式,只要有输出就会返回0,没有则返回非0。
内容的提问来源于stack exchange,提问作者Abhijeet Banerjee
相关产品推荐
相关产品推荐

