Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash List files not matching an array of patterns

I am not that experienced with bash and I have a question.

I am trying to select some files (let's say ls for this example) that do not match a certain array o patterns.

I have files named Test,Test1,Test2,Test3,Test4,Test5,Test6,Test7,Test8,Test9,Test10 that I need to select in two groups.

1st group is Test5,Test6,Test7,Test8,Test9,Test10 which I can list by using:

ls -l T*@(5|6|7|8|9|10) or ls -l T*{5,6,7,8,9,10}

The 2nd group is the tricky one (for me) because of the Test & Test1 files. I am trying to invert the previous selection/listing.. or somehow select the rest. I have tried several things with no luck:

ls -l T*[!5678910]
ls -l T*[!@(5|6|7|8|9|10)]
ls -l T*[!5][!6][!7][!8][!9][!10]
ls -l T*@(1|2|3|4|)

p.s: the actual filenames have extra characters after the number.

like image 880
tfonias74 Avatar asked Mar 10 '17 11:03

tfonias74


3 Answers

You can inverse a pattern like this:

# enable extended glob, if disabled, it will not function
shopt -s extglob

# create our files
touch {Test,Test1,Test2,Test3,Test4,Test5,Test6,Test7,Test8,Test9,Test10}

# list files with matching pattern
ls -1 T*@(5|6|7|8|9|10)
Test10
Test5
Test6
Test7
Test8
Test9


# list files with NOT matching pattern
ls -1 T!(*@(5|6|7|8|9|10))
Test
Test1
Test2
Test3
Test4
like image 88
anubhava Avatar answered Oct 30 '22 05:10

anubhava


You may use an empty string as an option in the list:

ls -l Test*{,1,2,3,4}

[EDIT] But in general I don't see a way to do inverted match in bash alone. Also I see now that there may be other characters after numbers (I suppose non-numerical, or you would have no way to distinguish). I would use ´grep´ , possibly with ´-v´ flag for negation.

ls -1 |  grep -v "Test\(\(5\)\|\(6\)\|\(7\)\|\(8\)\\|\(9\)\|\(10\)\)"
like image 2
marek.jancuska Avatar answered Oct 30 '22 05:10

marek.jancuska


I'm not sure why it doesn't work with *, but it works with more specific patterns:

ls -l Test@(1|2|3|4|)
ls -l Test?([1-4])
ls -l T+([^0-9])?([1-4])
like image 1
choroba Avatar answered Oct 30 '22 05:10

choroba