Search code examples
bashclasscharacterparameter-expansion

Bash character class parameter expansion inconsistent behavior


Here are all the steps which seems to suggest to me a bug in bash.

Version and platform information

--> cat /etc/os-release
NAME="Ubuntu"
VERSION="14.04.5 LTS, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04.5 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
--> bash --version
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Detailed steps of the issue:

--> ls
--> touch a aa aaa b bb bbb
--> ls *[:alpha:]
a  aa  aaa
--> rm a aa aaa
--> ls *[:alpha:]
ls: cannot access *[:alpha:]: No such file or directory

Why would '*[:alpha:]' list 'a*' filenames and not 'b*' ones?

For those who wonder, to get proper behavior, one has to use *([[:alpha:]]). But that doesn't explain the inconsistency shown up here.


Solution

  • There is no inconsistency. With the duplicate characters removed, [:alpha:] is equivalent to [:alph]. And so ls *[:alpha:] is really equivalent to ls *[:alph], and only a, aa and aaa match that, so that's what you got as output. After you deleted those files, ls *[:alph] will find no matches, hence the error you received.

    If you want to use the [:alpha:] character class, you need to write as [[:alpha:]].