Loom
Loom

Reputation: 9986

How to know file name from a pipeline of commands

I search for some text in some file list. I have the following command to print these lines:

ls -1 *.log | xargs tail --lines=10000 | grep text_for_search

The command output contains all of occurrences of text_for_search, but it hasn't information from which file the occurrences are. How to modify the command to provide this information too?


Actually log files are gigabytes in size, so it's essential to use tail --lines=10000 for each of them

Upvotes: 0

Views: 107

Answers (4)

anubhava
anubhava

Reputation: 784878

You must avoid parsing ls output and use shell's for loop to iterate through all *.log files:

for f in *.log; do
  awk -v c=$(wc -l < "$f") 'NR>c-10000 && /text_for_search/{print FILENAME ":" $0}' "$f"
done

EDIT:

You can use awk to search through all *.log files:

awk 'NR>=10000 && /text_for_search/ {print FILENAME ":" $0}' *.log

Upvotes: 1

Vijay
Vijay

Reputation: 67211

Replace your tail command with:

awk '{v[NR]=$0}END{for(i=NR-10000;i<=NR;i++)print FILENAME,v[i]}'

This above is just the replacement of the tail command except it adds a file name in the begining of each line.

Upvotes: 1

iwlagn
iwlagn

Reputation: 487

You can use find command:

find . -name "*.log" -exec grep text_for_search '{}' \;

grep will output filename and matched line. If you just need filenames - add -l switch to grep command.

'{}' - macro used for matched file name substitution in find's -exec command, \; indicates end of arguments for command, called by exec

Upvotes: 2

Tom Fenech
Tom Fenech

Reputation: 74596

You could just use a loop instead, which will keep track of the file name for you:

for file in *.log; do 
    if tail --lines=-10000 "$file" | grep -q text_for_search; then
        echo "$file"
    fi
done

The -q switch to grep suppresses the output, returning a 0 (success) exit code if the pattern is matched.

Upvotes: 2

Related Questions