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
(ls glob* &>/dev/null && echo Files found) || echo No file found
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.
[ `ls glob* 2>/dev/null | head -n 1` ] && echo true
I like
exists() {
[ -e "$1" ]
}
if exists glob*; then
echo found
else
echo not found
fi
This is both readable and efficient (unless there are a huge number of files).
The main drawback is that it's much more subtle than it looks, and I sometimes feel compelled to add a long comment.
If there's a match, "glob*"
is expanded by the shell and all the matches are passed to exists()
, which checks the first one and ignores the rest.
If there's no match, "glob*"
is passed to exists()
and found not to exist there either.
Edit: there may be a false positive, see comment
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
This abomination seems to work:
#!/usr/bin/env bash
shopt -s nullglob
if [ "`echo *py`" != "" ]; then
echo "Glob matched"
else
echo "Glob did not match"
fi
It probably requires bash, not sh.
This works because the nullglob option causes the glob to evaluate to an empty string if there are no matches. Thus any non-empty output from the echo command indicates that the glob matched something.