2

I want to search a directory (excluding paths that contain any of certain words, ideally a regex pattern) and find all files with contents that match my query (ideally a regex pattern, which I'd make case-insensitive) and were modified between 2 specific dates.

Based on this answer, my current command is:

find /mnt/c/code -type f -mtime -100 -mtime +5 -print0 |
xargs -0 grep -l -v "firstUnwantedTerm" 'mySearchTerm'

Apparently this query does not exclude all paths that contain "firstUnwantedTerm".

Also, I'd love if the results could be sorted by modified datetime descending, displaying: their modified time, the full file name, and the search query (maybe in a different color in the console) surrounded by some context where it was seen.

grep -rnwl --exclude='*firstUnwantedTerm*' '/mnt/c/code' -e "mySearchTerm" from here also seemed to be a step in the right direction in the sense that it seems to correctly exclude my exclusion term, but it doesn't filter by modified datetime and doesn't output all the desired fields, of course.

Ryan
  • 22,332
  • 31
  • 176
  • 357

1 Answers1

4

This is just quick & dirty and without sorting by date, but with 3 lines of context before/after each match and coloured matches:

find ~/mnt/c/code -type f -mtime -100 -mtime +5 | grep -v 'someUnwantedPath' | xargs -I '{}' sh -c "ls -l '{}' && grep --color -C 3 -h 'mySearchTerm' '{}'"

Broken down into pieces with some explanation:

# Find regular files between 100 and 5 days old (modification time)
find ~/mnt/c/code -type f -mtime -100 -mtime +5 |

  # Remove unwanted files from list
  grep -v 'someUnwantedPath' |

  # List each file, then find search term in each file,
  # highlighting matches and
  # showing 3 lines of context above and below each match
  xargs -I '{}' sh -c "ls -l '{}' && grep --color -C 3 -h 'mySearchTerm' '{}'"

I think you can take it from here. Of course this can be made more beautiful and fulfill all your requirements, but I just had a couple of minutes and leave it to the UNIX gurus to beat me and make this whole thing 200% better.


Update: version 2 without xargs and with only one grep command:

find ~/mnt/c/code -type f -mtime -30 -mtime +25 ! -path '*someUnwantedPath*' -exec stat -c "%y %s %n" {} \; -exec grep --color -C 3 -h 'mySearchTerm' {} \;

! -path '*someUnwantedPath*' filters out unwanted paths, and the two -exec subcommands list candidate files and then show the grep results (which could also be empty), just like before. Please note that I changed from using ls -l to stat -c "%y %s %n" in order to list file date, size and name (just modify as you wish).

Again, with additional line breaks for readability:

find ~/mnt/c/code
  -type f
  -mtime -30 -mtime +25
  ! -path '*someUnwantedPath*'
  -exec stat -c "%y %s %n" {} \;
  -exec grep --color -C 3 -h 'mySearchTerm' {} \;
halfer
  • 19,824
  • 17
  • 99
  • 186
kriegaex
  • 63,017
  • 15
  • 111
  • 202
  • I appreciate the hint. – Ryan Aug 26 '20 at 19:26
  • **Update:** added solution without `xargs` for filtering unwanted paths, with `-exec` sub-commands and with `stat` instead of `ls`. – kriegaex Aug 27 '20 at 00:48
  • I wonder why you did not accept my answer and your only feedback was "thanks for the hint". If the answer was unacceptable, why didn't you provide a more qualified feedback, telling me what is wrong with it, or write your own answer with a better solution? – kriegaex Sep 03 '20 at 11:05
  • 1
    Of course with lots of extra code it would be possible to sort by modification date, but `find` lists by path name, so that would have required more transformations, caching, maybe revisiting the same file etc. So this is not something to be done easily in a one-liner and rather suited to a special shell script. I figured it was not worth the effort, just to make the output more beautiful. – kriegaex Sep 03 '20 at 11:09
  • I apologize. And I appreciate your comment explaining about the sorting. I meant to award you the bounty. I'm still very confused by the bounty system. – Ryan Sep 04 '20 at 12:43
  • 1
    I don't answer lots of bounty questions, but I think what happened is that I got half of the bounty automatically because, even though you had not accepted the answer and not manually assigned the bounty to me either, the answer had enough upvotes to account for a partial bounty. Probably this is written somewhere in more detail, but I am not a pro in this area either. – kriegaex Sep 05 '20 at 02:08