Test whether a glob has any matches in bash

2019-01-01 15:03发布

If I want to check for the existence of a single file, I can test for it using test -e filename or [ -e filename ].

Supposing I have a glob and I want to know whether any files exist whose names match the glob. The glob can match 0 files (in which case I need to do nothing), or it can match 1 or more files (in which case I need to do something). How can I test whether a glob has any matches? (I don't care how many matches there are, and it would be best if I could do this with one if statement and no loops (simply because I find that most readable).

(test -e glob* fails if the glob matches more than one file.)

标签: bash glob
18条回答
长期被迫恋爱
2楼-- · 2019-01-01 15:30

In Bash, you can glob to an array; if the glob didn't match, your array will contain a single entry that doesn't correspond to an existing file:

#!/bin/bash

shellglob='*.sh'

scripts=($shellglob)

if [ -e "${scripts[0]}" ]
then stat "${scripts[@]}"
fi

Note: if you have nullglob set, scripts will be an empty array, and you should test with [ "${scripts[*]}" ] or with [ "${#scripts[*]}" != 0 ] instead. If you're writing a library that must work with or without nullglob, you'll want

if [ "${scripts[*]}" ] && [ -e "${scripts[0]}" ]

An advantage of this approach is that you then have the list of files you want to work with, rather than having to repeat the glob operation.

查看更多
浮光初槿花落
3楼-- · 2019-01-01 15:31

I did not see this answer, so I thought I'd put it out there:

set -- glob*
[ -f "$1" ] && echo "found $@"
查看更多
栀子花@的思念
4楼-- · 2019-01-01 15:32

To simplify The MYYN's answer somewhat, based on his idea:

M=(*py)
if [ -e ${M[0]} ]; then
  echo Found
else
  echo Not Found
fi
查看更多
几人难应
5楼-- · 2019-01-01 15:34

[ ls glob* 2>/dev/null | head -n 1 ] && echo true

查看更多
若你有天会懂
6楼-- · 2019-01-01 15:34
#!/usr/bin/env bash

# If it is set, then an unmatched glob is swept away entirely -- 
# replaced with a set of zero words -- 
# instead of remaining in place as a single word.
shopt -s nullglob

M=(*px)

if [ "${#M[*]}" -ge 1 ]; then
    echo "${#M[*]} matches."
else
    echo "No such files."
fi
查看更多
无色无味的生活
7楼-- · 2019-01-01 15:35

test -e has the unfortunate caveat that it considers broken symbolic links to not exist. So you may want to check for those, too.

function globexists {
  test -e "$1" -o -L "$1"
}

if globexists glob*; then
    echo found
else
    echo not found
fi
查看更多
登录 后发表回答