'How to find the most recent file containing a particular text in Unix?

I've a directory with thousands of files, many of them containing the text I'm looking for. I've to search only in a single directory. I need to find the most recently created file in the directory that contains a particular text, say "check".

I've tried grep, find and ls, but I can either find a list of files containing the text e.g.

 find . -type f -exec grep -l check {} +

or, the latest file in a directory using:

ls -t1 |  head -n 1

How can I combine both to get the latest file containing a particular text?



Solution 1:[1]

This is a simple way to do this:

find . -type f -exec grep -l check {} + | xargs ls -latr

Solution 2:[2]

Here's a decent way to do it:

grep -Pl '<PATTERN>' <DIR> -R \
  | xargs stat \
  | grep '(Change:|File:)' -P \
  | sed -r 's/^\s*//; s/File:.*\s(.*)`/\1/; '"s/'$//;"'s/Change:(.*)$/\1*/' \
  | tr -d '\n' \
  | tr '*' '\n' \
  | awk '{printf "%s %s %s\n", $3, $2, $1; }' \
  | sort -unr

Where <PATTERN> is the text you want to find and <DIR> is the path you want to look in.

Step-by-Step

  1. Grep
    • -R search recursively and follow symlinks.
    • -P PATTERN can be a perl regexp.
    • -l only print the names of files containing a match
  2. Xargs
    • xargs will run stat against each line of input coming from STDIN, which is the output from grep.
  3. Grep
    • -P allow perl regexp in PATTERN.
    1. '(Change:|File:)'
      We only want the filename and modification time from stat.
  4. Sed

    • -r enables support for extended regular expressions

    1. s/^\s*//
      Deletes all whitespace from the start of each line.
    2. s/File:.*\s(.*)/\1/

      Replace File:, any immediate whitespace, and ` with the contents of group 1 (.*)

    3. s/'$//
      Delete the single-quote from lines ending with one.

    4. s/Change:(.*)$/\1*/
      Delete Change: and add a * at the end of each line.
  5. Tr
    • -d delete the character instead of replacing it.
    1. '\n'
      Delete newlines
    2. '*' '\n'
      Replace asterisks with newlines.
  6. Awk
    1. Print output like so HH:MM:SS.MS DATE FILE
  7. Sort
    • -u discard duplicate lines
      We only want each file to appear once--we don't care how many times the pattern has appeared in the files.
    • -n compare according to string numerical value
      We're comparing timestamps.
    • -r reverse the result of comparisons
      So the most recent file is at the top instead.

I use * here because none of the files in my use-case had an asterisk in their name. You can use whatever character you like, so long as it doesn't appear in any of the filenames or in the output from stat.

Solution 3:[3]

May be a late response, hope this helps someone later.

I am not a pro in Shell, but found below one works for me and this is very simple to use and understand.

grep '<Search String>' $(ls -t1 |  head -n 1)

Solution 4:[4]

props is not available in useEffect scope. You must pass it as a dependency in useEffect.

Try following:

 useEffect(() =>{
        console.log(props.questions)
        console.log(Object.values(props.questions))
        checkAnswer()
    }, [props])

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Alexej Magura
Solution 3 Ram
Solution 4 Shreekesh Murkar