6

I am using the ls utility and my command looks like this:

$ ls x?[a-c]*

What is the output of such command? So far I understand (and I hope it's right) that it will list items that:

  • start with x
  • third letter is {a,b,c}
  • anything after third letter, does not matter, is included

My question is, what does the ? (question mark) represent? What condition is it?

Thank you in advance.

2
  • 1
    You seem to have groked it. Except that it is bash not ls that is evaluating the pattern. Therefore you can use in in any command (not just ls). Jun 17, 2018 at 14:56
  • 2
    On most systems, it would only be {a,b,c} in the C/POSIX locale. For instance, in a en_US.UTF-8 locale on a GNU system (with glibc 2.23), [a-c] in bash matches on ABabcªÀÁÂÃÄÅÆàáâãäåæĀāĂ㥹ƁǍǎǞǟǠǡǢǣǺǻǼǽȀȁȂȃȦȧɓḀḁḂḃḄḅḆḇẚẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặ. You'd need [abc] to match on a, b or c only. Jun 17, 2018 at 15:00

1 Answer 1

11

It is not an ls feature, it's a bash feature and it's described in the “Pattern Matching” section in bash(1):

The special pattern characters have the following meanings:

*

      Matches any string, including the null string.  When the globstar shell option is enabled, and * is used in a pathname expansion context, two adjacent *s used as a single pattern will match all files and zero or more directories and subdirectories.  If followed by a /, two adjacent *s will match only directories and subdirectories.
?
      Matches any single character.
[...]
      Matches any one of the enclosed characters.  A pair of characters separated by a hyphen denotes a range expression; any character that falls between those two characters, inclusive, using the current locale's collating sequence and character set, is matched.  If the first character following the [ is a ! or a ^ then any character not enclosed is matched.  The sorting order of characters in range expressions is determined by the current locale and the values of the LC_COLLATE or LC_ALL shell variables, if set.  To obtain the traditional interpretation of range expressions, where [a-d] is equivalent to [abcd], set value of the LC_ALL shell variable to C, or enable the globasciiranges shell option.  A - may be matched by including it as the first or last character in the set.  A ] may be matched by including it as the first character in the set.

Your understanding is also not entirely correct – ? means any single character, so the expression x?[a-c]* would match xQcFoo.bar, xmabc and x1abut also xabc - the point is that {a,b,c} may be also the second letter, not only the third. Output of ls x?[a-c]* command will be a list of files that match x?[a-c]* pattern. Or, if there are no such files, the shell won't substitute x?[a-c]* with anything, so ls will try to list the file literally named x?[a-c]*.

7
  • 1
    Also note that if any of those files are of type directory, it will list their content. Generally, you want to use the -d option when you pass globs to ls. Also not that if there's no matching file, in bash, and unless the nullglob or failglob options are enabled, x?[a-c]* will be passed verbatim to ls. And if that file exists, it will be listed (even though it doesn't match the pattern). If not, ls (not the shell) will report an error. Jun 17, 2018 at 15:07
  • @StéphaneChazelas: If you're not trying to list contents, why use ls at all? Just use echo, unless you're also passing -l or something else that gets you additional information.
    – Kevin
    Jun 17, 2018 at 17:41
  • @Kevin, yes, exactly, people use ls *.txt thinking ls is listing the *.txt files, while it's actually the shell that does the listing and ls is only doing the displays, and also things that were not asked for (like listing the content of directories or interpreting file names that start with - as options). You'd need ls -d -- *.txt, and the only reason why you'd want that over printf '%s\n' *.txt (remember echo can't be used for arbitrary data) is to work around he problem that some shells leave globs unexpanded when they don't match. And that printf still outputs (tbc) Jun 17, 2018 at 18:15
  • (continue) when there's no argument to satisfy the formant (you don't have this problem with csh, tcsh, fish, zsh...) Jun 17, 2018 at 18:16
  • @StéphaneChazelas: use-case: In most people's default setup, ls does colour highlighting to show you if any of your *.txt files are symlinks. Of course it's also faster to type than printf '%s\n' *.txt, and formats the listing into columns. The text processing could be done a different way, but wouldn't highlight symlinks (or files with their x bit set, which sometimes happens when they're from another system.) Jun 17, 2018 at 21:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .