1
grep -r "print " */*/*/*/*/*.py */*/*/*/*.py */*/*/*.py */*/*.py

I want to look for all the ocurrences of "print " in all .py files in subdirectories inside my current directory. I came up with the above command and it works, but I'd like to find some sort of way to have an arbitrary depth because some of my files are on a depth of 3, others on 4 and others on even higher depths.

I'm pretty sure I can maybe use find and then pipe, but I'm not quite sure how.

David Gomes
  • 5,644
  • 16
  • 60
  • 103

4 Answers4

4

On bash and zsh you can use **:

grep "print " **/*.py

If the double star is not available on your shell of choice, then you can use xargs like:

find . -regex ".*\.py" -print0 | xargs -0 grep "print "
Stefano Sanfilippo
  • 32,265
  • 7
  • 79
  • 80
3

Try using find with -exec

find -type f -name '*.py' -exec grep -H 'print ' {} \;

For better performance, use find with xargs

find -type f -name '*.py' -print0 | xargs -0 grep 'print '
jkshah
  • 11,387
  • 6
  • 35
  • 45
  • No, for better performance use `find -type f -name '*.py' -exec grep -H 'print ' {} +` (with the `+` at the end!) – gniourf_gniourf Nov 02 '13 at 17:48
  • @gniourf_gniourf Ohh! I didn't know that option and may be third alternative. But I read somewhere that `xargs` approach is most effective. Correct me if I'am wrong. Thanks for your suggestion. – jkshah Nov 02 '13 at 17:53
  • I doubt the `xargs` method will be the most effective. It will have a pipe and a fork overhead compared to the `find -type f -name '*.py' -exec grep -H 'print ' {} +` method. – gniourf_gniourf Nov 02 '13 at 17:55
  • @gniourf_gniourf Please refer to [accepted answer of this SO question](http://stackoverflow.com/questions/5200591/how-to-use-grep-efficiently). And if you still disagree, some reference would be helpful. – jkshah Nov 02 '13 at 17:56
  • 1
    After several naive testings it seems the `xargs` way wins. I've edited my answer accordingly. Thank you again for pointing this out! – gniourf_gniourf Nov 02 '13 at 18:13
  • @gniourf_gniourf You're welcome! I had not tested it by myself and was relying on expert opinions and test results. Thanks for confirming! – jkshah Nov 02 '13 at 19:11
2

No need for a pipe.

find some/dir -name '*.py' -exec grep -H "print " {} \;
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • This is highly inefficient, since `grep` will be executed once per each python file. For big directory trees, it matters. – Stefano Sanfilippo Nov 02 '13 at 16:36
  • Thank you very much, problem with that solution (and also the one by @jkshah) is that they don't list the file name and location before the print thing. – David Gomes Nov 02 '13 at 16:36
1

If your grep supports the --include option, use it:

grep -R --include='*.py' 'print ' .

That's definitely the best option here. The xargs option in the other answers might be better as it uses multithreading in an efficient way.


Funny: to tell whether your grep handles this option, you can of course man grep then search in there for the string --include with the keystrokes /--include or you can:

man grep | grep -- --include

or

grep --help | grep -- --include

Otherwise, since no one mentionned the -exec ... + way of using find, here it is:

find -type f -name '*.py' -exec grep -H 'print ' {} +

but that's not as good as the grep --include way. But as said before, the multithreading capabilities of the methods with xargs should perform better.

gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104