複数のファイルで最後に現れる文字列を探す

複数のファイルで最後に現れる文字列を探す

最後に表示される文字列を見つけるには、複数のログファイル(すべて過去24時間以内に作成され、すべて同じディレクトリに保存されている)を検索する必要があります。私が書いたコマンドは次のとおりです。

find . -mtime 1 | grep fileprefix | xargs grep 'search string' | tail -1

しかし、これはファイルの最後の行だけを返します。すべての行を得るために調整する方法についての提案はありますか?

答え1

すべてが1つのディレクトリにある場合は、次のことができます。

for file in *fileprefix*; do
    grep 'search string' "$file" | tail -1
done

tac大容量ファイルの場合は、ファイルを逆順に(最後の行から)印刷してから、最初の項目に合わせてgrep -m1作業を高速化することをお勧めします。これにより、ファイル全体を読む必要がなくなります。

for file in *fileprefix*; do
    tac file | grep -m1 'search string'
done

どちらも一致するディレクトリがないとしますfileprefix。エラーがあると、無視できるエラーが発生します。これが問題の場合は、ファイルを確認してください。

 for file in *fileprefix*; do
    [ -f "$file" ] && tac file | grep -m1 'search string'
 done

ファイル名も印刷する必要がある場合は、-Hgrep呼び出しにその名前を追加してください。またはgrep、サポートされていない場合は検索も実行するように指示します/dev/null。これは出力を変更しませんが、grep複数のファイルが提供されるため、常に各ヒットのファイル名を印刷します。

for file in *fileprefix*; do
    grep 'search string' "$file" /dev/null | tail -1
done

答え2

GNU機能を仮定すると:

find . -mtime -1 -exec bash -c \
'for f; do tac "$f" | grep -m1 fileprefix; done' _ {} +

答え3

find . ! -name . -prune -mtime 1 -name 'fileprefix*' \
     -exec sed -se'/searchstring/h;$!d;x' {} +

sed...スタンドアロンファイルオプションとPOSIXをサポートするGNUがある場合に-s機能しますfind

ただし、ディレクトリを読み取ろうとすることはあまり役に立ちません。通常のファイルに絞り込むと、パイプやシリアルデバイスファイルを読み取ることができないため、修飾子を追加する必要があります! -type d-type f

ロジックは非常に簡単です。前のスペースを一致する入力行のコピーで上書きし、出力からsed各入力ファイルの最後の入力行を除くすべての行を削除します。最後の行に達すると保持スペースとパターンスペースが変更されるため、ファイルの読み込み中に最後のイベントが見つかった場合は自動的に出力に印刷され、それ以外の場合は空行が作成されます。hsearchstringdxsearchstring/./!d(必要でない場合はスクリプトの最後に追加)sed

sedこれは、約65,000個の入力ファイルまたは制限ARG_MAXに関係なく、1回の呼び出しを実行します。これはパフォーマンスが非常に優れており、実装が非常に単純なソリューションでなければなりません。

最新のGNUのファイル名も必要な場合は、sedこのコマンドを使用して別の行にF書き込むか、または。find-print+

答え4

find . -mtime 1 -name 'fileprefix*' -exec grep -Hn 'search string' {} + |
    sort -t: -k1,2 -n | 
    awk -F: '{key=$1 ; $1="" ; $2="" ; gsub(/^  /,"",$0); a[key]=$0} 
             END {for (key in a) { print key ":" a[key] }}'

これは、GNUgrep-Hオプションを使用-nして一致するすべてのファイル名と行番号を常に印刷し、ファイル名と行番号でソートし、それをawkにパイプして各ファイル名の最後の一致を配列に保存し、最後に印刷します。

これはやや暴力的な方法ですが、効果があります。

関連情報