I want to recursively grep on all files in subdirectories with extension csv but select only those files that are less than 4M in size. Is this correct way to do?

find . -type f -size -4M | grep --include \*.csv 'pattern'

This command selects all the files with .csv, basically doesn't limit to less than 4M in size, although find alone correctly finds all files less than 4M.


First I'll set up some fake data:

$ for fileno in {1..4}; do for line in {1..100000}; do printf "%d,%d,%d,%d,%d,%d,%d,%d\n" $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM; done > ~/tmp/big-fake-${fileno}.csv; done
$ for fileno in {1..4}; do for line in {1..50000}; do printf "%d,%d,%d,%d,%d,%d,%d,%d\n" $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM; done > ~/tmp/small-fake-$fileno.csv; done

Let's verify it has the properties you're interested in:

$ du -b tmp/*.csv
4528666 tmp/big-fake-1.csv
4529227 tmp/big-fake-2.csv
4529173 tmp/big-fake-3.csv
4528782 tmp/big-fake-4.csv
2263714 tmp/small-fake-1.csv
2264028 tmp/small-fake-2.csv
2264398 tmp/small-fake-3.csv
2265134 tmp/small-fake-4.csv

Now let's look for some kind of pattern in the smaller files:

$ find tmp/ -type f -iregex ".*\.csv" -size -4M -exec grep '1,1,1' {} +

Naturally the grep here can take other flags, eg -l if you're only interested in the filenames which contain the pattern you want.

The {} + you can think of as kind of a template for "insert a list of filenames discovered by find in place of the brackets." Since Grep is happy to take a list of filenames rather than one at a time, this is superior to -exec grep '1,1,1' {} \;, which would launch a new instance of Grep for every separate file, one at a time.

This -exec flag I believe is a GNU-ism and not available in other types of find. I think on other platforms they go with a find -print0 | xargs -0 type of pattern. (I'm sure someone will leave a comment elaborating on this.)

  • 1
    No, print0 and similar is non-portable. -exec exists since find exists on UNIX. The problem with GNU find is that it ignored newer features (until I asked them to implement it...) of the real find and e.g. did not implement support for the -exec + that was added 1988.That non-portable xarags toy was introduced by GNU find instead of looking for good ideas like execplus from David Korn from 1988. – schily Feb 4 at 21:48
  • 1
    @ewr3243 using -type f – schily Feb 4 at 21:52
  • I'll edit the answer, although I don't think it would affect anything because directories won't be matching -iregex ".*\.csv" – cryptarch Feb 4 at 21:57
  • @shily Thanks for insight! – cryptarch Feb 4 at 22:00
  • I used your answer and modified with -name "*.csv". How different is that from your version? – ewr3243 Feb 4 at 22:02

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