Search code examples
bashglob

How to use [[ == ]] properly to match a glob?


Bash's manpage teaches that [[ == ]] matches patterns. In Bash therefore, why does the following not print matched?

Z=abc; [[ "$Z" == 'a*' ]] && echo 'matched'

The following however does indeed print matched:

Z=abc; [[ "$Z" == a* ]] && echo 'matched'

Isn't this exactly backward? Why does the a*, without the quotes, not immediately expand to list whatever filenames happen to begin with the letter a in the current directory? And besides, why doesn't the quoted 'a*' work in any case?


Solution

  • While the existing answer is correct, I don't believe that it tells the full story.

    Globs have two uses. There is a difference in behaviour between globs inside a [[ ]] construct which test the contents of a variable against a pattern and other globs, which expand to list a range of files. In either case, if you put quotes around character, it will be interpreted literally and not expanded.

    It is also worth mentioning that the variable on the left hand side doesn't need to be quoted after the [[, so you could write your code like this:

    Z=abc; [[ $Z == a* ]] && echo 'matched'
    

    It is also possible to use a single = but the == looks more familiar to those coming from other coding backgrounds, so personally I prefer to use it in bash as well. As mentioned in the comments, the single = is the more widely compatible, as it is used to test string equality in all of POSIX-compliant shells, e.g. [ "$a" = "abc" ]. For this reason you may prefer to use it in bash as well.

    As always, Greg's wiki contains some good information on the subject of pattern matching in bash.