如果我想检查单个文件是否存在,我可以使用test -e filename或[-e filename]进行测试。
假设我有一个glob,我想知道是否有文件名与glob匹配的文件存在。glob可以匹配0个文件(在这种情况下,我不需要做任何事情),也可以匹配1个或多个文件(在这种情况下,我需要做一些事情)。我如何测试一个glob是否有任何匹配?(我不在乎有多少匹配,这将是最好的,如果我能做到这一点与一个if语句和没有循环(只是因为我发现最易读)。
(如果glob匹配多个文件,则test -e glob*失败。)
在Bash中,你可以glob到数组;如果glob不匹配,你的数组将包含一个与现有文件不对应的条目:
#!/bin/bash
shellglob='*.sh'
scripts=($shellglob)
if [ -e "${scripts[0]}" ]
then stat "${scripts[@]}"
fi
注意:如果你设置了nullglob, scripts将是一个空数组,你应该使用["${scripts[*]}"]或["${#scripts[*]}" != 0]来测试。如果您正在编写一个必须使用或不使用nullglob的库,那么您将需要
if [ "${scripts[*]}" ] && [ -e "${scripts[0]}" ]
这种方法的一个优点是,这样您就有了想要处理的文件列表,而不必重复glob操作。
nullglob shell选项实际上是bashism。
为了避免繁琐的保存和恢复nullglob状态,我只在扩展glob的subshell中设置它:
if test -n "$(shopt -s nullglob; echo glob*)"
then
echo found
else
echo not found
fi
为了获得更好的可移植性和更灵活的通配符,使用find:
if test -n "$(find . -maxdepth 1 -name 'glob*' -print -quit)"
then
echo found
else
echo not found
fi
显式-print -quit操作用于查找,而不是默认的隐式-print操作,以便查找在找到第一个匹配搜索条件的文件时立即退出。当许多文件匹配时,这应该比echo glob*或ls glob*运行得快得多,并且它还避免了过度填充扩展命令行的可能性(一些shell有4K长度限制)。
如果find感觉有点多余,可能匹配的文件数量很少,请使用stat:
if stat -t glob* >/dev/null 2>&1
then
echo found
else
echo not found
fi