0

I have found a very odd situation where grep does not work as expected when ran from within one particular directory.

While looking at some archive data I found that grep worked correctly in the first and third level directories, but not in the second.

[root@Server ANM]# ls data/atg/|head -n5
2017-01-04-07:31
2017-01-04-08:01
2017-01-04-08:31
2017-01-04-09:01
2017-01-04-09:31
[root@Server ANM]# ls data/atg/|head -n5|grep 201[1-8]
2017-01-04-07:31
2017-01-04-08:01
2017-01-04-08:31
2017-01-04-09:01
2017-01-04-09:31
[root@Server ANM]# cd data
[root@Server data]# ls atg/|head -n5|grep 201[1-8]
[root@Server data]# ls atg/|head -n5|grep 201
2017-01-04-07:31
2017-01-04-08:01
2017-01-04-08:31
2017-01-04-09:01
2017-01-04-09:31
[root@Server data]# ls atg/|head -n5|\grep 201[1-8]
[root@Server data]# ls atg/|head -n5|/bin/grep 201[1-8]
[root@Server data]# ls atg/|head -n5|grep "201[1-8]"
2017-01-04-07:31
2017-01-04-08:01
2017-01-04-08:31
2017-01-04-09:01
2017-01-04-09:31
[root@Server data]# cd atg
[root@Server atg]# ls | head -n5 | grep 201[1-8]
2017-01-04-07:31
2017-01-04-08:01
2017-01-04-08:31
2017-01-04-09:01
2017-01-04-09:31

Notice that grep works correctly in the ANM/ directory, it fails when in ANM/data, and it works correctly from in the ANM/data/atg directory.

Using /bin/grep does not fix it, also removing stripping aliasing does not. The only thing that works is to quote the regex.

I don't normally use quotes with grep, but I am thinking I should start.

Not looking for help with this as I have found the workaround.

These directories will be archived to tape soon and I expect the problem will go away then. If anyone has ideas for something to check, post a comment.

There are about 1000 entries in the directory so I don't see the pipe failing.

I did notice that with set -x the shell reports the command differently.

This is when it fails

+ grep 2017 2018

This is when it works

+ grep '201[1-8]'

Same command, different directory.

LinuxGuru
  • 341
  • 2
  • 11
  • 3
    `ls | grep` is *innately* unreliable, and should never be used by anyone. See [ParsingLs](http://mywiki.wooledge.org/ParsingLs) -- and [use `find` instead](http://mywiki.wooledge.org/UsingFind) (when you have a job that shell globs can't do on their own -- which doesn't appear to be the case here). – Charles Duffy Jun 07 '19 at 19:44
  • 6
    `201[1-8]` will be intercepted and expanded *by the shell* as a glob construct (filename expansion) if you don't quote it - but only if that matches a filename. That will happen before `grep` is called, so it won't see it as an RE. Rule of thumb - *always* quote `grep` (and `sed`, etc) regular expressions in shell statements. – cdarke Jun 07 '19 at 19:45
  • 2
    `matches=( atg/201[1-8]* ); [[ -e ${matches[0]} ]] && printf '%s\n' "${matches[@]:0:5}"`, f/e, is a shell-glob-based solution. – Charles Duffy Jun 07 '19 at 19:47
  • You should *always* use quotes (generally single-quotes) around the regular expressions you pass to `grep`. There's a lot of overlap between regex and shell syntax metacharacters, so there's a lot of opportunity for things to go wrong without proper quoting. – Gordon Davisson Jun 07 '19 at 23:21

0 Answers0