How to grep and execute a command (for every match)

Grep

Grep Problem Overview


How to grep in one file and execute for every match a command?

File:

foo
bar
42
foo
bar

I want to execute to execute for example date for every match on foo.

Following try doesn't work:

grep file foo | date %s.%N

How to do that?

Grep Solutions


Solution 1 - Grep

grep file foo | while read line ; do echo "$line" | date %s.%N ; done

More readably in a script:

grep file foo | while read line
do
    echo "$line" | date %s.%N
done

For each line of input, read will put the value into the variable $line, and the while statement will execute the loop body between do and done. Since the value is now in a variable and not stdin, I've used echo to push it back into stdin, but you could just do date %s.%N "$line", assuming date works that way.

Avoid using for line in `grep file foo` which is similar, because for always breaks on spaces and this becomes a nightmare for reading lists of files:

 find . -iname "*blah*.dat" | while read filename; do ....

would fail with for.

Solution 2 - Grep

What you really need is a xargs command. http://en.wikipedia.org/wiki/Xargs

grep file foo | xargs date %s.%N

example of matching some files and converting matches to the full windows path in Cygwin environment

$ find $(pwd) -type f -exec ls -1 {} \; | grep '\(_en\|_es\|_zh\)\.\(path\)$' | xargs cygpath -w

Solution 3 - Grep

grep command_string file | sh - 

Solution 4 - Grep

There is an interesting command in linux for that: xargs, It allows You to use the output from previous command(grep, ls, find, etc.) as the input for a custom execution but with several options that allows You to even execute the custom command in parallel. Below some examples:

Based in your question, here is how to print the date with format "%s.%N" for each "foo" match in file.txt:

grep "foo" file.txt | xargs -I {} date +%s.%N

A more interesting use is creating a file for each match, but in this case if matches are identical the file will be override:

grep "foo" file.txt | xargs -I {} touch {}

If You want to concatenate a custom date to the file created

grep "foo" file.txt | xargs -I {} touch "{}`date +%s.%N`"

Imagine the matches are file names and You want to make a backup of them:

grep "foo" file.txt | xargs -I {} cp {} "{}.backup"

And finally for xargs using the custom date in the backupName

grep "foo" file.txt | xargs -I {} cp {} "{}`date +%s.%N`"

For more info about options like parallel execution of xargs visit: https://en.wikipedia.org/wiki/Xargs and for date formats: https://www.thegeekstuff.com/2013/05/date-command-examples/

Extra I have found also a normal for command useful in this scenarios It is simpler but less versatile below are the equivalent for above examples:

for i in `grep "foo" test.txt`; do date +%s.%N; done
for i in `grep "foo" test.txt`; do touch ${i}; done
for i in `grep "foo" test.txt`; do touch "${i}`date +%s.%N`"; done
for i in `grep "foo" test.txt`; do cp ${i} "${i}.backup2"; done
for i in `grep "foo" test.txt`; do cp ${i} "${i}.backup2`date +%s.%N`"; done

Have Fun!!!

Solution 5 - Grep

grep may need --line-buffered option to emit each matching line when it matches it, otherwise it buffers up to 4K byte before printing match lines, which defeats the goal here, e.g.

tail -f source | grep --line-buffered "expression | xargs ...

Solution 6 - Grep

    grep search_string files_to_search | sh

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRazerView Question on Stackoverflow
Solution 1 - GrepPhil HView Answer on Stackoverflow
Solution 2 - GrepMarko KukovecView Answer on Stackoverflow
Solution 3 - GrepJamesView Answer on Stackoverflow
Solution 4 - GrepEnrique PalacioView Answer on Stackoverflow
Solution 5 - GrepEmmanuel BlotView Answer on Stackoverflow
Solution 6 - GrepRaveen KumarView Answer on Stackoverflow