Better to explain on examples.

I can:

find . -name "*.py" -type f > output.txt

But how can I store the output to the same file for:

find . -name "*.py" -type f -exec grep "something" {} \

I can't just do

find . -name "*.py" -type f -exec grep "something" {} \ > output.txt

6 Answers 6


If I understand you correctly this is what you want to do:

find . -name '*.py' -print0 | xargs -0 grep 'something' > output.txt

Find all files with extension .py, grep only rows that contain something and save the rows in output.txt. If the output.txt file exists, it will be truncated, otherwise it will be created.

Using -exec:

find . -name '*.py' -exec grep 'something' {} \; > output.txt

I'm incorporating Chris Downs comment here: The above command will result in grep being executed as many times as find finds pathnames that passes the given tests (only the single -name test above). However, if you replace the \; with a +, grep is called with multiple pathnames from find (up to a certain limit).

See question Using semicolon (;) vs plus (+) with exec in find for more on the subject.

  • 21
    Use + instead of \;, it will improve execution time significantly (since it will contatenate arguments prior to execution until ARG_MAX).
    – Chris Down
    Nov 6, 2011 at 14:31
  • Now I understand the power of xargs! Thanks!
    – domih
    Apr 6, 2016 at 8:45
  • 7
    Usegrep -H if you want to include the filename of the file in the output.
    – Steinar
    Apr 23, 2018 at 13:18
  • Use option 1. And add LC_ALL=C right before xargs to get a lot of extra speed. And you can use a -P6 flag on xargs to run in parallel with (in this case) 6 processes (feel free to change the number from 6 to something higher or lower, to see what's faster on your machine and on your search). Reference: unix.stackexchange.com/questions/131535/… May 22, 2020 at 8:24
  • Using + instead of \; will pass multiple files to grep, and if any file in that set contains the text 'something', all those files will pass the test. So it won't do what you want. Nov 17, 2020 at 19:37

If you want to save all the matching lines across all files in output.txt, your last command does work, except that you're missing the required ; at the end of the command.

find . -name "*.py" -type f -exec grep "something" {} \; > output.txt

If you want each run of grep to produce output to a different file, run a shell to compute the output file name and perform the redirection.

find . -name "*.py" -type f -exec sh -c 'grep "something" <"$0" >"$0.txt"' {} \;
  • the last one really nice :D
    – bakytn
    Sep 20, 2011 at 3:32
  • To expand on @gilles answer to make it a little more informative, especially if the list of files you're dealing with is large, you can report the file name (relative path) of each file along with the grep'ed results using this: find . -name "*.py" -type f -exec grep "something" {} \; -print > output.txt And if you'd like to see the line numbers of the grep'ed lines you can, of course, use grep -n "something"
    – JJMpls
    Jul 24, 2014 at 2:27

For the record, grep has --include and --exclude arguments that you can use to filter the files it searches:

grep -r --include="*.py" "something" > output.txt
  • 2
    At least GNU grep does.
    – phk
    Nov 1, 2016 at 20:43

Use tee:

find . -name '*.py' | tee output.txt | xargs grep 'something'

The caveat, is if you have any files with special characters (including spaces) that xargs and grep won't work well with (a file.txt will be interpreted as two files, a and file.txt). The alternative to that is to use either the -x or -print0, but either of those will pollute your output.txt. The -x will use \ to escape certain special characters and this will be in output.txt. The -print0 will use a null byte as a field separator (which also requires xargs -0) and output.txt will look like one long contiguous line of text.

How you deal (or don't) with this is up to you.

grep -n CThread '`find . -name "*.cpp"`'

To find files in a directory and search for a string in the result: find $dir -name "*partoffilename*" | xargs -I '{}' grep -ri $searchstring {}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.