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
  • 34,963

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
  • 142,475