22

I am using the following command for counting the lines of text in JAVA files:

find . -name '*.java' | xargs wc -l

How can I modify the find command parameters to match more than one file extension? For example, I would like use the above operation for CPP, C, and H files.

2
  • This question is actually about the find command, since that is where you are searching for matching files.
    – iglvzx
    Commented Apr 24, 2012 at 23:48
  • 1
    Also, use either the find -print0 | xargs -0 construct or even better and simpler: find . -name '*.cpp' -o -name '*.c' -o -name '*.h' -exec wc -l {} +. This will avoid any file name issues (blank spaces, new lines and so on) and is (very) good custom. Commented Apr 25, 2012 at 6:39

6 Answers 6

24

Use the -o option for an OR. For example, this would list .cpp, .c and .h files:

find . -name \*.cpp -o -name \*.c -o -name \*.h
3
  • Ah. The * no longer needs to be escaped if formatted as code. Totally overlooked that. :)
    – iglvzx
    Commented Apr 25, 2012 at 0:44
  • Yep, it took three edits by two people but we got it.
    – JOTN
    Commented Apr 25, 2012 at 1:06
  • 3
    This didn't work for me on OSX (only matched the last -name *.ext) -- I had to use parentheses as suggested by @smokinguns below.
    – Gilead
    Commented May 8, 2015 at 11:37
2

You will need to use the -o option. For example the statement below finds all png, jpg and gif files in a folder.

find . \( -iname \*.png -o -iname \*.jpg -o -iname \*.gif \)

I use the -iname option so that the match is case insensitive.

1
  • 1
    iname isn't available on all versions of find.
    – JOTN
    Commented Apr 25, 2012 at 1:07
2
$ find /path/ -name '*.cpp' -or -name '*.c' -or -name '*.h'

The “-or” says I’m looking for either/both of two sets.

I recently wrote a quick guide to using find with boolean operators here: http://jamesfishwick.com/2012/linux-find-and-boolean-operators

1

While all answers are more or less the same, I don't find them readable with multiple name and Boolean operators in-between.

I think this may be more elegant solution:

$ find . -type f | grep -E "\.java$|\.cpp$|\.c$"

Let's break this up

  • find . finds all files recursively in current path (change to some other path if you need)
  • -type fnarrows the search only to files (not too much of a speed gain, but still...)
  • | grep -E I used this to get grep recognize or (|) operator in Mac OS X which uses FreeBSD grep, GNU grep does not need that (check in your man file).
  • "\.java$|\.cpp$|\.c$" regular expression which includes files whose name ends with .java, .cpp, and .c (add ones you need)

You can then pipe the resulting list for further processing, e.g.

$ find . -type f | grep -E "\.java$|\.cpp$|\.c$" | xargs sed -i '' $'/s/\r$//'

This example removes DOS/Windows CRLF line ending for OS X/Linux LF (this is also OS X sed syntax, check for your version specifics).

2
  • I wanted to find all video file types using 25 different extension matching parameters. This was the only approach that worked for me. (Ubuntu 14.04 LTS)
    – Elder Geek
    Commented Nov 2, 2016 at 14:35
  • How well does this perform when you only have a small number of matching files on a large file system with lot of files that don't match the grep pattern?
    – dvvrt
    Commented Jan 7, 2021 at 16:08
0

Use

find path/to/dir -name "*.ext1" -o -name "*.ext2"

Explanation

  1. The first parameter is the directory you want to search.
  2. By default find does recursion.
  3. The -o stands for -or. So above means search for this wildcard OR this one. If you have only one pattern then no need for -o.
  4. The quotes around the wildcard pattern are required.
0

With the GNU version of find you can also use -regex or -iregex (i.e. case-insensitive):

find . -iregex '.*\.\(txt\|html\|js\|ts\|jsx\|css\)'

-regex is not supported with the BSD/macOS ootb flavour of find, on a mac you'll need to install it, for example, with brew install findutils, and then call with gfind . -regex ....

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .