Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Match file names using Linux Shell regex

Tags:

regex

linux

shell

I need a way to match file names in directory.

For example I have three files:

CAt_DoG_ZebRa.TXT
MOUSE_lion_deer_BIRD.TXT
fIsh_biRD_LION.TXT

I am not regex expert by any means, however I've used something like this in SnapLogic and Pentaho before:

(?i).*(?=.*bird)(?=.*lion).*.TXT

The above would match all file names that contain the words 'bird' and 'lion' with case being ignored and the order of the words would not matter. Very powerful! So it would match these two:

MOUSE_lion_deer_BIRD.TXT    
fIsh_biRD_LION.TXT

I tried lots of variations of the above in conjunction with find and grep to no avail. For example:

find . -regex ".*/(?i).*(?=.*bird)(?=.*lion).*.TXT"

The above find does not match anything.

Can anyone recommend a way to do this?

like image 807
Soyf Avatar asked Dec 19 '14 19:12

Soyf


3 Answers

# ls
asdafsdfdBirdasfdfd.txt      dasdbirdbfdgdlionb.txt       fgdfLionqweBirdaqw.txt   
# ls | /usr/gnu/bin/grep -i -E '.*(bird.*lion|lion.*bird).*\.txt'
dasdbirdbfdgdlionb.txt
fgdfLionqweBirdaqw.txt

a trick: when you writing some regular expression using look ahead or look behind, doubt it, and either change another way to write it or think about whether regular expression is a suitable tool for this problem.

like image 25
Jason Hu Avatar answered Nov 13 '22 13:11

Jason Hu


shopt -s globstar   # enable recursive globs
shopt -s nocaseglob # make globs case-insensitive
for file in ./**/*bird*lion*.txt; do
  echo "found: $file"
done

...or, if you didn't care about order between those words:

shopt -s globstar   # enable recursive globs
shopt -s nocaseglob # make globs case-insensitive
shopt -s extglob    # enable extended globbing syntax
for file in ./**/*@(bird*lion|lion*bird)*.txt; do
  echo "found: $file"
done
like image 183
Charles Duffy Avatar answered Nov 13 '22 13:11

Charles Duffy


First, find doesn't support PCRE regex engine, so this a solution for your problem, with perl and bash (recursive) :

 bash -c "shopt -s globstar; perl -lne 'print if /i.*bird/i and /i.*lion/i' **"

This solution work with all filenames matching bird and lion, in any orders

like image 1
Gilles Quenot Avatar answered Nov 13 '22 11:11

Gilles Quenot