6

I mean to match (with ls, rm, etc.) files with names test10 to test18, test30 to test38, test22 to test23, with a single regex, in bash. I tried many variants around

$ ll "test([1,3][0-8]|22|23)" 

but I couldn't make it work. What is the correct way to do this?

Raffa
  • 32,237
  • As a RegEx side note, it might be worth noting that , in [1,3] will be matched literally and will not be treated as a special character like e.g. the class range character - (I just got the impression you are trying to use it in a special way) ... Also, Bash (and alike shells) can actually do RegEx matching ... See for example Can globbing be used to search file contents? ... However, in your use case, what you want is indeed shell filename globbing or brace expansion and not RegEx matching. – Raffa Mar 13 '24 at 18:49

1 Answers1

8

In this context, shells uses glob patterns, not regular expressions1. In bash, you could use a ksh-style extended glob (enabled by default in an interactive bash shell - in a script, you will need to set with shopt -s extglob):

ls test@([13][0-8]|2[23])

or

ls test@(1[0-8]|2[23]|3[0-8])

In zsh, you could use numeric ranges instead (although it supports ksh-style extended globs as well):

ls test(<10-18>|<22-23>|<30-38>)

Alternatively, you could use brace expansion (in both bash and zsh) - but note this doesn't actually perform matching so you will get errors unless all the named files are actually present:

ls test{{1,3}{0..8},22,23}

  1. Coincidentally, ([13][0-8]|2[23]) and (1[0-8]|2[23]|3[0-8]) are also valid extended regular expressions, so you could use them in a find expression for example:

    find . -maxdepth 1 -regextype posix-extended -regex '.*/test([13][0-8]|2[23])'
    
steeldriver
  • 136,215
  • 21
  • 243
  • 336