Find the last occurence of a string in a given filetype in all subdirectories
Solution 1
I will use something like:
for i in `find . -name "*.out" -type f`;
do
grep -l 'string' $i
grep 'string' $i|tail -1
done
With 1st grep you will have filename and below (second grep) the content.
This works as long as the file names don't contain whitespace or \[*?
. See cuonglm's answer for a robust solution.
Solution 2
Assume you are in parent directory of sub directories:
find . -type f -name '*.out' -exec sh -c '
for f do
grep "string" /dev/null "$f" | tail -n 1
done
' sh {} +
Solution 3
With zsh
on a GNU system:
for f (**/*.out(.)) tac < $f | grep --label=$f -m1 string
Solution 4
With gnu
tools, you could use a single invocation of gawk
:
awk '/pattern/{l=$0} ENDFILE{if (l) {print FILENAME ":" l; l=""}}' **/*.out
(if line matches store it into l
; at the end of each file, if l
is not empty print file name and l
then reset l
)
or sed
:
sed -ns '/pattern/h;${x;//{F;p}}' **/*.out
(if line matches, copy to h
old space; if la$
t line, ex
change hold space w. pattern space; if it matches, p
rint F
ile name and line)
though the output is different - file name and corresponding last matching line are on separate lines - but if piped to another sed
e.g.
sed -ns '/pattern/h;${x;//{F;p}}' **/*.out |sed '$!N;s/\n/:/'
it will mimic grep
output1.
The above assume bash (v. 4 with shopt -s globstar
) or zsh. To include hidden files add shopt -s dotglob
(bash) or setopt dotglob
(zsh).
1: as long none of those file names contains newline characters.
Related videos on Youtube
rambalachandran
An engineer trying to get insights from data
Updated on September 18, 2022Comments
-
rambalachandran over 1 year
I have multiple sub-directories each with different depths. I need to search for the last occurrence of a string in a specific file type (say
*.out
). How can I accomplish this?I have tried:
grep -r 'string' **/*.out | tail -1
But that gives me only the last string of the last file.
-
cuonglm almost 9 yearsWhat's the different between
the last string of the last file
andthe last occurrence of a string
? -
rambalachandran almost 9 yearsIf I have 100 directories with each possessing a file of type .out, I need the command to print out the last occurence of string in all 100 files. The above command only prints it out for one file (which I think is the last file accessed)
-
lcd047 almost 9 years@cuonglm: The difference is the former omits the relevant occurrences in other files.
-
-
rambalachandran almost 9 yearsGreat this works. Is it possible to get the path for the file as well before the grep
-
Atul Vekariya almost 9 yearsFrom what I know about grep I can print content of only filename. To print both I can use second grep. See my addon to the answer
-
rambalachandran almost 9 yearsThis works. Is it possible to obtain the filepath before the grep step? Also what does sh -c & sh {} + do?
-
Atul Vekariya almost 9 yearsUnfortunately this will print the name of every file with this extension (independent if contain or not the string)
-
lcd047 almost 9 years@WanderingMind: Add
/dev/null
after"$f"
to trickgrep
to show you the filename.sc -c ...
is needed to make the pipegrep | tail
work.sh {} +
sends the filenames tosh
. -
cuonglm almost 9 years@WanderingMind: I invite you to read unix.stackexchange.com/a/152723/38906 .
-
cuonglm almost 9 years@RomeoNinov: Fixed it!
-
rambalachandran almost 9 yearsThank you. It works in my case. Although I think as discussed in other answer, this command will provide me paths of files that don't contain the string.
-
Atul Vekariya almost 9 yearsNo, the script above will print only files, which contain 'string' string inside