Created SC2245 (markdown)

Vidar Holen
2019-01-13 16:39:01 -08:00
parent 6f6b812423
commit 49ac6c65c4

49
SC2245.md Normal file

@@ -0,0 +1,49 @@
## -d only applies to the first expansion of this glob. Use a loop to check any/all.
### Problematic code:
```sh
if [ -f ksh* ]
then
echo "The file exists"
fi
```
### Correct code:
```sh
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:
```sh
[ -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!