如果我想检查单个文件是否存在,我可以使用test -e filename或[-e filename]进行测试。

假设我有一个glob,我想知道是否有文件名与glob匹配的文件存在。glob可以匹配0个文件(在这种情况下,我不需要做任何事情),也可以匹配1个或多个文件(在这种情况下,我需要做一些事情)。我如何测试一个glob是否有任何匹配?(我不在乎有多少匹配,这将是最好的,如果我能做到这一点与一个if语句和没有循环(只是因为我发现最易读)。

(如果glob匹配多个文件,则test -e glob*失败。)


当前回答

如果你想在遍历这些文件之前测试它们是否存在,你可以使用这个模式:

  for F in glob*; do
    if [[ ! -f $F ]]; then break; fi
    
    ...

  done

如果glob不匹配任何内容,$F将是未展开的glob(在本例中为'glob*'),如果同名文件不存在,则跳过循环的剩余部分。

其他回答

#!/bin/bash
set nullglob
touch /tmp/foo1 /tmp/foo2 /tmp/foo3
FOUND=0
for FILE in /tmp/foo*
do
    FOUND=$((${FOUND} + 1))
done
if [ ${FOUND} -gt 0 ]; then
    echo "I found ${FOUND} matches"
else
    echo "No matches found"
fi

ls | grep - q“glob *。”

这不是最有效的解决方案(如果目录中有大量文件,它可能会比较慢),但它很简单,易于阅读,而且它的优点是正则表达式比普通的Bash glob模式更强大。

(ls glob* &>/dev/null && echo Files found) || echo No file found
set -- glob*
if [ -f "$1" ]; then
  echo "It matched"
fi

解释

当没有匹配glob*时,$1将包含'glob*'。test -f "$1"不会为真,因为glob*文件不存在。

为什么这比其他选择更好

这适用于sh和衍生品:KornShell和Bash。它不会创建任何子壳。$(..)和'…'命令创建子shell;它们分叉一个进程,因此比这个解决方案慢。

如果你想在遍历这些文件之前测试它们是否存在,你可以使用这个模式:

  for F in glob*; do
    if [[ ! -f $F ]]; then break; fi
    
    ...

  done

如果glob不匹配任何内容,$F将是未展开的glob(在本例中为'glob*'),如果同名文件不存在,则跳过循环的剩余部分。