grep, start from end of file question

XOR != OR

[H]F Junkie
Joined
Jun 17, 2003
Messages
11,547
I have a directory full of log files that I need to search through, and I am only interested in the last match in the file. I know I can only match n number of lines ( in my case, 1 ), but I'd like to begin matching from the end of the file, not the start of it.

I can't use tail or any other utility to feed files in to grep either, I need to retain the filename in the output.

Kind of a strange request, anybody have any advice on this?
 
Couldn't you just append the filename to the output?

Sounds like a job for perl if you really need to read a log backwards.
 
grep someString `ls -rt *log` | tail -1

that work for you?
 
grep someString `ls -rt *log` | tail -1

that work for you?

Wouldn't that just be the last match in the last file?
How about this?
Code:
ls *log | xargs -I%  sh -c 'grep -H theString % | tail -n1'

For each file, start a subshell that runs grep on that file and sends the output of that through tail. The -H makes grep prefix every matching line with the filename.
 
Wouldn't that just be the last match in the last file?
How about this?
Code:
ls *log | xargs -I%  sh -c 'grep -H theString % | tail -n1'
For each file, start a subshell that runs grep on that file and sends the output of that through tail. The -H makes grep prefix every matching line with the filename.

dont EVER parse the output of ls! it is broken for scripting
Likesie do not rely on xargs it is broken for quite a few cases
 
dont EVER parse the output of ls! it is broken for scripting
Likesie do not rely on xargs it is broken for quite a few cases

Well, it depends on how sensible his log file names, ls, xargs, shell and settings are. I'm on a conservative FreeBSD system at the moment, and both ls and xargs do the right things. No guarantees in other environments.
A more careful take on the same idea is this:
Code:
find . -maxdepth 1 -name "*log"  -print0 |\
 xargs -0 -I% sh -c 'grep -H theString % | tail -n1'
(Or you can try to fit it into the -exec statement of find.)
For a one-off, I'd call that a waste of time if the former works (which it did for me).


Anyway. You'll still get issues with filenames with whitespace in, but if you have any of those in your logfiles, having to find the right quoting solution is the least you deserve. :D
 
Last edited:
for i in `ls *log`;do grep -H pattern $i|tail -1;done

As long as you know that there are no spaces in the file name, ls will work just fine. Other wise you will have to play with quoting.

Also, grep has different options on different *nix. For example, Solaris grep does not have -H.
 
for i in `ls *log`;do grep -H pattern $i|tail -1;done

As long as you know that there are no spaces in the file name, ls will work just fine. Other wise you will have to play with quoting.

Also, grep has different options on different *nix. For example, Solaris grep does not have -H.

Ah yes. I tend to use tcsh, so I usually go for solutions not directly involving my shell - but that's a nice minimal variant.
 
Ah yes. I tend to use tcsh, so I usually go for solutions not directly involving my shell - but that's a nice minimal variant.

Its not so much the shell, its more todo with the actual coreutils app

GNU coreutils tend to have additional option which makes portability across all *NIX VERY hard - sed is like this as well and awk. Likewise GNU coreutils have additional commands (eg stats) over what would be concidered coreutils for other *NIX
 
tac file.txt | grep some_regex

I would say this would be what you're looking for. Except if you want to output the last match in EVERY log file, you'd probably have to use a small script, something like thus:

Code:
#!/bin/bash

path="/path/to/logs"
pattern="some_pattern"

# if you have directories in your path, you can also do:  for file in `find $path -type f`; do
for file in $path; do
    echo "file: $file"
    tac $file | grep "$pattern" | tail -n 1
    echo ""
done

I didn't test that, but it should be pretty close.
 
Last edited:
It's not so much the shell, it's more to do with the actual coreutils app.


I wasn't refering to the arguments, but the actual structure of "how to get, split, and apply grep to the file names" - which he did as a bash/ksh/sh for loop, while I let xargs do the lifting.
 
Back
Top