Regular expression problem(s) in Bash: [^negate] doesn't seem to work
Are you sure what you want is happening?
When you run ls /directory | grep '[^term]'
you are essentially grepping for not the letters t e r m. This means if a file has other letters in its name it will still appear in the output of ls
. Take the following directory for instance:
$ ls
alpha brave bravo charlie delta
Now if I run ls |grep '^[brav]'
I get the following:
$ ls |grep '^[brav]'
alpha
brave
bravo
As you can see, not only did I get brave
and bravo
I also got alpha
because the character class []
will get any letter from that list.
Consequently, if I run ls |grep '[^brav]'
I will get all the files that do not contain the characters b r a v anywhere in the name.
$ ls |grep '[^brav]'
alpha
bravo
brave
charlie
delta
If you notice it included the entire directory listing because all the files had at least one letter that was not included in the character class.
So as Kanvuanza said, to grep for the inverse of "term" as opposed to the characters t e r m
you should do it using grep -v
.
For instance:
$ ls |grep -v 'brav'
alpha
charlie
delta
Also if you don't want the files that have any characters in the class use grep -v '[term]'
. That will keep any files from showing up that have any of those characters. (Kanvuanza's answer)
For instance:
$ ls |grep -v '[brav]'
As you can see there were no files listed because all the files in this directory included at least one letter from that class.
Addendum:
I wanted to add that using PCRE it is possible to use just regex to filter out using negate expressions. To do this you would use something known as a negative look-ahead regex: (?!<regex>)
.
So using the example above, you can do something like this to get results you want without using grep
flags.
$ ls | grep -P '^(?!brav)'
alpha
charlie
delta
To deconstruct that regex, it first matches on a start of a line ^
and then looks for strings that do not match brav
to follow afterwards. Only alpha
, charlie
, and delta
match so those are the only ones that are printed.
I guess that grep -v
flag does what you want. From the man page:
-v, --invert-match
Invert the sense of matching, to select non-matching lines.
You can use ls /directory | grep -v [term]
to print any non matching lines.