-d only applies to the first expansion of this glob. Use a loop to check any/all.
Problematic code:
#!/bin/ksh
if [ -f ksh* ]
then
echo "The file exists"
fi
Correct code:
#!/bin/ksh
for f in ksh*
do
if [ -f "$f" ]
then
echo "Found a matching file: $f"
fi
done
Rationale:
Ksh has the curious behavior of ignoring anything after an unrecognized flag to test
/[
, which means that file checking operators against globs will effectively apply the operator to the first expansion:
[ -f ksh* ] # This
[ -f ksh93u ksh93u.tar ksh93u.tar.gz ] # Becomes this
[ -f ksh93u ] # And is interpreted like this
This is an issue when you have multiple matches for a glob. Instead of checking some or all, it only checks the first result and ignores the rest. To ensure that all results are considered (either to check that any or all results match the operator), use a loop explicitly.
If you really only want to match the first result of the glob expansion as sorted alphabetically in the current locale, you can make this intention explicit:
matches=( ksh* )
if [ -f "${matches[0]}" ]
then
echo "The first result is a file"
fi
Exceptions:
If you only care that entries exists, use -e
. ShellCheck does not warn in this case, since all files resulting from glob expansion necessarily exist.
Related resources:
- Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!