1

someone can explain me why this regexp doesn't work in grep?

ls -la ./ | grep -E '^d.*\<\..*\>$'

In my (wrong) opinion this have to show me the line of the directory with a name that start with ".", because:

  • ^d -> keep lines that start with character "d"
  • .* -> none or any combination of characters
  • $ -> end of the line

The problem is that I don't understand this:

  • \< -> start of the word
  • . -> escape the point
  • .* -> none or any combination of characters
  • > -> end of the word

So I thought that this part of regexp keeps the lines that contain words that start with point and end with a combination of characters.

With this "ls -la" that regexp with grep shows none of result:

[arch dirtest]$ ls -la
total 52
drwxr-xr-x  6 siv users 4096 10 nov 00.41 .
drwx------ 59 siv users 4096  9 nov 23.15 ..
drwxr-xr-x  2 siv users 4096 10 nov 00.41 .test
drwxr-xr-x  2 siv users 4096 10 nov 00.41 test1
drwxr-xr-x  2 siv users 4096 10 nov 00.41 test2

2 Answers 2

4

Your regular expression doesn't work because . is not a word character. Grep only considers a-z, A-Z, 0-9 and _ to be word characters.

In any case, this is really not the right way to do this. First of all, parsing ls is very fragile and almost never a good idea. Here are some other ways of listing directories whose name starts with a .:

find . -type d -name '.*'

Or, if you don't want it to descend into subdirectories (and if you have GNU find, the default on Linux):

find . -maxdepth 1 -type d   -name '.*' 

Alternatively, you could just use echo and a shell glob:

echo .*

That will also show files. To avoid that, use a loop like:

for i in .*; do [ -d "$i" ] && printf '%s\n' "$i"; done
5
  • Sorry, I mispell the parameter. The right parameter is "-E". Anyway I understand that it is not a good way to parse ls, but I have to do this in text for university so I can't modify this. Maybe this command may not work but the "right" answer for the test is that it finds directories with the name that start with a point. Don't you think so, too?
    – sivlab
    Nov 10, 2015 at 0:35
  • 2
    the "some reason" is that . isn't a word-constituent character as defined by grep. word characters are letters, digits, and underscore. so \<\. will never match anything.
    – cas
    Nov 10, 2015 at 4:34
  • @cas d'oh! Of course, I should have known. That's what I get for answering questions at 2am.
    – terdon
    Nov 10, 2015 at 10:19
  • @siv-lab What is the question? No, parsing ls is never the right answer, whatever the question was. If your teacher told you you have to use ls, then he's an idiot. And no, even if id did work, that would not find directories whose names start with a dot, only directories whose name contains a dot after a non-word character. So, for example foo .bar would also be found.
    – terdon
    Nov 10, 2015 at 10:24
  • Yeah I get it, parsing "ls" is a bad way. Thanks for your explanation.
    – sivlab
    Nov 10, 2015 at 11:51
1

You seem to have omitted a device method after -D?

ls -la ./ | grep -D skip '^d.*\<\..*\>$'

Anyway ... the problem is that you're searching for a beginning-of-word boundary, \<, followed by a literal dot, \.. This will always fail, because a dot is not considered a word character. Quote from info grep for GNU grep:

`-w'
`--word-regexp'
     ... Word-constituent characters are letters, digits, and the underscore.

Replacing \< with a space seems to work reliably. However, I agree with user:terdon that parsing the output from ls -la is fragile, and there are better ways to get what you want.

1
  • Sorry I misspelled the parameter. The right parameter is "-E". So the problem is that the point is not considered a chatacter. I understand that parse "ls" is not a good idea but I have no other choices (see above the reply at terdon's comment). Thanks you
    – sivlab
    Nov 10, 2015 at 0:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .