我试图检查一个文件是否存在,但与通配符。以下是我的例子:
if [ -f "xorg-x11-fonts*" ]; then
printf "BLAH"
fi
我也试过不加双引号。
我试图检查一个文件是否存在,但与通配符。以下是我的例子:
if [ -f "xorg-x11-fonts*" ]; then
printf "BLAH"
fi
我也试过不加双引号。
当前回答
如果网络文件夹中有大量文件,使用通配符是有问题的(速度,或命令行参数溢出)。
最后我得到了:
if [ -n "$(find somedir/that_may_not_exist_yet -maxdepth 1 -name \*.ext -print -quit)" ] ; then
echo Such file exists
fi
其他回答
您可以执行以下操作:
set -- xorg-x11-fonts*
if [ -f "$1" ]; then
printf "BLAH"
fi
这适用于sh和衍生品:KornShell和Bash。它不会创建任何子壳。$(..)和'…在其他解决方案中使用的命令会创建一个子shell:它们会派生一个进程,而且效率很低。当然,它可以处理多个文件,而且这个解决方案可能是最快的,或者仅次于最快的。
当没有任何匹配时,它也能工作。没有必要像某位评论员所说的那样使用nullglob。$1将包含原始的测试名称,因此test -f $1将不会成功,因为$1文件不存在。
下面是针对您的特定问题的解决方案,它不需要for循环或ls、find等外部命令。
if [ "$(echo xorg-x11-fonts*)" != "xorg-x11-fonts*" ]; then
printf "BLAH"
fi
正如您所看到的,它只是比您希望的稍微复杂一些,并且依赖于这样一个事实,即如果shell不能展开glob,这意味着不存在具有该glob的文件,echo将按原样输出glob,这允许我们仅做字符串比较来检查是否存在这些文件。
但是,如果我们要概括这个过程,我们应该考虑到这样一个事实,即文件的名称和/或路径中可能包含空格,并且glob char可以合理地扩展为零(在您的示例中,这将是文件名正好为xorg-x11-fonts的文件的情况)。
这可以通过bash中的以下函数来实现。
function doesAnyFileExist {
local arg="$*"
local files=($arg)
[ ${#files[@]} -gt 1 ] || [ ${#files[@]} -eq 1 ] && [ -e "${files[0]}" ]
}
回到您的示例,可以像这样调用它。
if doesAnyFileExist "xorg-x11-fonts*"; then
printf "BLAH"
fi
Glob展开应该发生在函数内部,以便它正常工作,这就是为什么我把参数放在引号中,这就是函数体中的第一行:因此任何多个参数(可能是函数外部Glob展开的结果,以及一个虚假的形参)将合并为一个。另一种方法是,如果有多个实参,就引发错误,还有一种方法是忽略除第一个实参以外的所有实参。
函数体中的第二行将files var设置为由glob扩展到的所有文件名组成的数组,每个数组元素对应一个文件名。如果文件名包含空格是可以的,每个数组元素将按原样包含文件名,包括空格。
函数体中的第三行做了两件事:
It first checks whether there's more than one element in the array. If so, it means the glob surely got expanded to something (due to what we did on the 1st line), which in turn implies that at least one file matching the glob exist, which is all we wanted to know. If at step 1. we discovered that we got less than 2 elements in the array, then we check whether we got one and if so we check whether that one exist, the usual way. We need to do this extra check in order to account for function arguments without glob chars, in which case the array contains only one, unexpanded, element.
对于Bash脚本,最直接和最有效的方法是:
if compgen -G "${PROJECT_DIR}/*.png" > /dev/null; then
echo "pattern exists!"
fi
即使在有数百万个文件的目录中,这也会非常快地工作,而且不涉及新的子shell。
源
最简单的应该是依赖ls返回值(当文件不存在时,它返回非零):
if ls /path/to/your/files* 1> /dev/null 2>&1; then
echo "files do exist"
else
echo "files do not exist"
fi
我重定向ls输出,使其完全静音。
下面是一个同样依赖于glob展开的优化,但避免使用ls:
for f in /path/to/your/files*; do
## Check if the glob gets expanded to existing files.
## If not, f here will be exactly the pattern above
## and the exists test will evaluate to false.
[ -e "$f" ] && echo "files do exist" || echo "files do not exist"
## This is all we needed to know, so we can break after the first iteration
break
done
这与grok12的答案非常相似,但它避免了在整个列表中进行不必要的迭代。
试试这个
fileTarget="xorg-x11-fonts*"
filesFound=$(ls $fileTarget)
case ${filesFound} in
"" ) printf "NO files found for target=${fileTarget}\n" ;;
* ) printf "FileTarget Files found=${filesFound}\n" ;;
esac
Test
fileTarget="*.html" # Where I have some HTML documents in the current directory
FileTarget Files found=Baby21.html
baby22.html
charlie 22.html
charlie21.html
charlie22.html
charlie23.html
fileTarget="xorg-x11-fonts*"
NO files found for target=xorg-x11-fonts*
注意,这只适用于当前目录,或者变量fileTarget包含您想要检查的路径的地方。
Use:
files=(xorg-x11-fonts*)
if [ -e "${files[0]}" ];
then
printf "BLAH"
fi