Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linux vs. Unix file wildcards

Tags:

linux

bash

unix

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.

like image 725
Fitz Bushnell Avatar asked Mar 09 '23 09:03

Fitz Bushnell


1 Answers

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]*
like image 71
Nahuel Fouilleul Avatar answered Mar 15 '23 00:03

Nahuel Fouilleul