6

I have a need to search a certain folder for the newest created file and grep the contents for a pattern. I have had ok success so far using this command:

find /var/log/folder -type f -printf '%T+ %p\n' | sort | tail -n1 | xargs grep 'string to find'

This does find the latest file that has the match but I am getting an unexpected line in stdout.

$ find /var/log/folder -type f -printf '%T+ %p\n' |   sort | tail -n1 | xargs grep 'string to find'
grep: 2016-05-12+20:01:59.0570667340: No such file or directory
/var/log/folder/file:string to find

How can I change my command so it does not give me the "no such file or directory" line?

Stephen Kitt
  • 434,908
user53029
  • 2,813

2 Answers2

8

ls -1rt /path/to/files/ | tail -n1 will find the newest file in a directory (in terms of modification time); pass that as an argument to grep:

grep 'string to find' "$(ls -1rt /path/to/files/ | tail -n1)"
DopeGhoti
  • 76,081
  • using -1art was returning "grep: .: Is a directory". I changed it to "ls -Art" and it works perfectly. So why was ls -1art was not working as expected? – user53029 May 13 '16 at 02:32
  • @DopeGhoti: You find that ls dir and ls dir/ do different things?  Not for me. – G-Man Says 'Reinstate Monica' May 13 '16 at 03:20
  • I do when I'm sleep-deprived and actually thinking of rsync and not ls. The problem was that I had -a in my answer which was including . and .., which might end up being the most recently changed thing in a directory. – DopeGhoti May 13 '16 at 03:31
  • Ok I have a problem. This works but I have to be inside the folder where the ls is ran. If the command specifies an absolute path, why do I have to be inside that folder for it to work? – user53029 May 13 '16 at 13:11
  • You can exclude directories with ls's -p option (which appends a '/' to directory names) and piping into grep -v '/$' before piping into tail -n 1. This works with at least GNU and FreeBSD's versions of ls. – cas May 13 '16 at 15:03
  • 1
    Clever and efficient... +1 for using only grep and not find or xargs. – Jesse Nickles Feb 16 '21 at 01:49
  • works on macos too. – JuanFernandoz Mar 11 '23 at 19:31
4

Here is a version that is safe for names with whitespace:

find /var/log/folder -type f -printf '%T@ %p\0' | sort -rz | sed -Ezn '1s/[^ ]* //p' | xargs --null grep string

How it works:

  • find /var/log/folder -type f -printf '%T@ %p\0'

    This looks for files and prints their modification time (seconds) followed by a space and their name followed by a nul character.

  • sort -rz

    This sorts the null-separated data.

  • sed -Ezn '1s/[^ ]* //p'

    sed -z handles nul-character delimited lines and this prints just the name of the newest file

  • xargs --null grep string

    This reads the null-separated file name and greps the string.

John1024
  • 74,655
  • GNU ls really needs a -0 or other NUL-delimiter option, like many other GNU tools (including head and tail) have gained over the last decade or so....it's starting to become surprising when you find a GNU tool that doesn't have one yet. – cas May 13 '16 at 14:57
  • @cas - that will probably never happen (and for good reason imo). – don_crissti May 13 '16 at 22:07
  • It still would be nice to have a tool that offered ease of use, like ls or ls -rt, but that you could count on to work reliably with modern file names. – John1024 May 13 '16 at 22:54