mirror of
https://github.com/koalaman/shellcheck.git
synced 2025-10-03 19:29:44 +08:00
Created SC2245 (markdown)
49
SC2245.md
Normal file
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!
|
Reference in New Issue
Block a user