0
votes

I am trying to get the 1st and second to the last line from multiple log files which has varying line numbers. And at the same time showing indicating the log filename before showing the content.Sample file content like below;

Process started
log entries here...
...........
...........
Process successful
Process ended

The desired output I am trying to achieve is like below;

05302016.log
Process started
Process successful
05312016.log
Process started
Process successful

How can this be done using either awk,sed,head,tail or any combination of these commands?

4
What should it do with empty files? How about files with only 1 or 2 lines?Ed Morton

4 Answers

1
votes
for file in *.log
    do
echo "$file"
head -1 "$file"
tail -2 "$file" |head -1


    done

result:

05302016.log
Process started1
Process successful1
05312016.log
Process started2
Process successful2
1
votes

This MAY do what you want depending on your requirements for handling empty files and files with fewer than 3 lines. With GNU awk for ENDFILE:

awk '
FNR==1 { first=$0 }
{ secondLast=prevLine; prevLine=$0 }
ENDFILE { print FILENAME ORS first ORS secondLast }
' *

With other awks:

awk '
FNR==1 {
    if (NR>1) {
        print prevFname ORS first ORS secondLast
    }
    prevFname = FILENAME
    first = $0
}
{ secondLast=prevLine; prevLine=$0 }
END {
    print FILENAME ORS first ORS secondLast
}
' *
0
votes

quick and dirty:

awk '{a[FNR]=$0}
    END{print FILENAME;print a[1];print a[FNR-1];print a[FNR]}' /path/*.log
0
votes

It may be easier with ed than sed. If all your files have at least 2 lines:

#!/bin/sh
nl=$'\n'
for i in *
do
    echo "$i"
    ed -s <<EOF
r $i
1p
\$-p
Q
EOF
done

(Note that in the here-document I had to escape the $ used to select the penultimate line - otherwise the shell will substitute $- with the active shell flags.)