Fitz Bushnell
Fitz Bushnell

Reputation: 41

Linux vs. Unix file wildcards

I'm looking to get a list of files in a directory in Linux starting with a capital letter. In Unix, it's a simple

ls [A-Z]*

In Linux, though, I'm seeing matches that don't seem to be case-sensitive:

=> ls
A.txt  b.txt  B.txt  c.txt  C.txt

=> ls [A]*
A.txt

=> ls [AB]*
A.txt  B.txt

=> ls [ABC]*
A.txt  B.txt  C.txt

 
=> ls [A-C]* A.txt  b.txt  B.txt  c.txt  C.txt

=> ls [b]*
b.txt

 
=> ls [a-c]* A.txt  b.txt  B.txt  c.txt

Running the same commands on the Unix side work as I'd expect. Is this the way Linux has always behaved? It's easy enough to work around this with awk, so I'm not looking for a solution in that way, but I'm wondering if I just never noticed this before. Thanks in advance.

Upvotes: 4

Views: 213

Answers (1)

Nahuel Fouilleul
Nahuel Fouilleul

Reputation: 19315

The result depends on different shell options, particularly: nocasematch nocaseglob And also LC_COLLATE variable (used in sort, [-], etc.)

$ shopt extglob nocasematch nocaseglob
extglob         off
nocasematch     off
nocaseglob      off


$ printf "%s\n" a A b B c C | sort
a
A
b
B
c
C

So [A-C] range contains b and c, but not a, also [a-c] should contain A but not C.

$ printf "%s\n" a A b B c C | LC_COLLATE=C sort
A
B
C
a
b
c

gives a different result.

$ LC_COLLATE=C ls [A-C]*

Should return expected result, this syntax sets the variable only for the new process execution (ls), but not in current shell process.

EDIT: thanks to comment, previous command is wrong because the expansion is processed before the LC_COLLATE be set, the simplest is to split into two commands.

$ export LC_COLLATE=C
$ ls [A-C]*

Upvotes: 7

Related Questions