MoonPoint Support Logo


Shop Amazon Warehouse Deals - Deep Discounts on Open-box and Used ProductsAmazon Warehouse Deals

Advanced Search
Sun Mon Tue Wed Thu Fri Sat

Sat, Mar 01, 2014 11:28 am

Using multiple conditions with find

The find command on Unix/Linux and Apple OS X systems allows you to specify multiple criteria to be used for a search. For instance, suppose I have a directory named man and a file named manual.txt. If I wanted to find any files or directories containing "man" within their names, I could issue the command below. If the directory in which the find command was executed contained a subdirectory named man and a text file named manual.txt, I would see the results shown below:
$ find . -name \*man\*

Note: the backslashes before the asterisks are "escape characters", i.e., they tell the shell not to interpret the asterisk before the find command sees it - see What is the difference between \*.xml and *.xml in find command in Linux/mac. Another alternative is to enclose the *man* within double quotes.

$ find . -name "*man*"

But, if I only want to find items that have "man" in the name which are directories, I could use the following to specify I only want to see items where the file is of type directory ("d" represents directory and "f" represents a regular file):

$ find . -name \*man\* -type d

By default, the find command will use a logical and for the two conditions, i.e., both conditions must be met. I could explicitly state I want to "and" the two conditions with a -a, but it isn't necessary to do so in this case.

$ find . -name \*man\* -a -type d

But what if I want to to specify a logical "or", i.e. that I want results returned where either of two conditions are met? E.g., suppose I want to find all files where the filename contains man or guide. Then I need to use a -o parameter.

$ find . -name "*man*" -o -name "*guide*"

Suppose I only wanted to see only files with man or guide in the filename that are "regular" files and not any directories. I could use -type f to specify that I only want to see regular files.

$ find . -name "*man*" -o -name "*guide*" -type f

As you can see, the directory man is still returned. To get the results I want, i.e., to not have the directory man appear in the results, I need to enclose the "or" condtions within parentheses.

$ find . \( -name "*man*" -o -name "*guide*" \) -type f

Note: you also need to "escape" the meaning of ( and ) by preceding them with the backslash escape character. Otherwise, you will get an "unexpected token" error message.

$ find . (-name "*man*" -o -name "*guide*") -type f
-bash: syntax error near unexpected token `('

And you need to put a space after the left parenthesis and before the right parenthesis or you will receive an "invalid predicate" error message.

$ find . \(-name "*man*" -o -name "*guide*"\) -type f
find: invalid predicate `(-name'

As another example, suppose I want to find all HTML or PHP files that contain the word "Geek" within them when the HTML files have a .html extension and the PHP files have a .php extension on the file names. Then I need to use a -o between the conditions to specify that I want to see results if the file has an extension of .html or .php.

$ find . \( -name "*.php" -o -name "*.html" \) -exec grep -i "Geeks" {} /dev/null \;

Whenever a file has a name that ends in .html or .php, the file contents are sent to the grep command for examination. To specify that I want to use a logical or, the -o is placed between -name "*.php" and -name "*.html". Again, I also have to include the two conditions within parentheses to ensure that the "or" condition is checked before sending the results to grep for examination of the contents of the files. If the parentheses aren't used, I would only see one of the files returned.

$ find . -name "*.php" -o -name "*.html" -exec grep -i "Geeks" {} /dev/null \;

[/os/unix/commands] permanent link

Once You Know, You Newegg AliExpress by

Shop Amazon Local - Subscribe to Deals in Your Neighborhood

Valid HTML 4.01 Transitional

Privacy Policy   Contact

Blosxom logo