Find with shell with different and/or conditions
Categories:
Mastering the find
Command with AND/OR Conditions in Shell
Learn how to use the powerful find
command in Linux and Unix-like systems to locate files and directories based on complex criteria involving logical AND and OR conditions.
The find
command is an indispensable tool for navigating and managing file systems in Linux and Unix-like environments. While its basic usage is straightforward, its true power lies in combining multiple search criteria using logical operators. This article will guide you through constructing find
commands with AND
and OR
conditions, enabling you to perform highly specific and efficient file searches.
Understanding find
's Logical Operators
The find
command processes expressions from left to right. By default, multiple expressions are implicitly combined with an AND
operator. To explicitly define AND
or OR
relationships, find
provides specific operators:
-a
or no operator (implicit): Logical AND. Both conditions must be true.-o
: Logical OR. At least one condition must be true.!
or-not
: Logical NOT. Negates the following condition.\(
\)
: Grouping. Used to control the order of evaluation, similar to parentheses in mathematical expressions. These need to be escaped to prevent the shell from interpreting them.
\(
and \)
when using them with find
to prevent the shell from interpreting them as special characters. This ensures find
receives them as arguments for grouping.Combining Conditions with AND
By default, when you specify multiple conditions without an explicit operator, find
treats them as an AND
operation. This means a file must satisfy all specified conditions to be included in the results. You can also explicitly use the -a
operator, though it's often omitted for brevity.
find . -type f -name "*.log" -size +1M
# Equivalent to:
find . -type f -a -name "*.log" -a -size +1M
Finding log files larger than 1MB
In the example above, find
will search the current directory (.
) for files (-type f
) that end with .log
(-name "*.log"
) AND are larger than 1 megabyte (-size +1M
). All three conditions must be met.
Combining Conditions with OR
The -o
operator allows you to find files that match at least one of several conditions. This is particularly useful when you're looking for files that could have different names, types, or other attributes.
find . -name "*.txt" -o -name "*.md"
Finding files ending with .txt OR .md
This command will locate all files in the current directory and its subdirectories that either end with .txt
OR end with .md
.
Advanced Logic with Grouping and NOT
When combining AND
and OR
conditions, the order of operations matters. find
evaluates AND
before OR
by default. To override this precedence and create more complex logic, you use escaped parentheses \(
\)
for grouping. The !
or -not
operator negates the condition that follows it.
find . -type f \( -name "*.log" -o -name "*.tmp" \) -size +10M
Finding log or temporary files larger than 10MB
Here, the parentheses ensure that find
first evaluates (-name "*.log" -o -name "*.tmp")
. This means it looks for files that are either .log
OR .tmp
. The result of this OR operation is then AND
ed with the -size +10M
condition. So, it finds files that are either .log
or .tmp
AND are larger than 10MB.
find . -type f -not -name "*.bak" -mtime -7
Finding files not ending with .bak, modified in the last 7 days
This command finds all regular files (-type f
) that do NOT end with .bak
(-not -name "*.bak"
) AND were modified within the last 7 days (-mtime -7
).
!
or -not
. It negates only the immediately following primary expression. For example, find . ! -name "*.txt" -o -name "*.log"
is different from find . ! \( -name "*.txt" -o -name "*.log" \)
.Logical flow for find . -type f \( -name "*.log" -o -name "*.tmp" \) -size +10M
Practical Examples
Let's look at a few more practical scenarios to solidify your understanding.
find /var/log -type f \( -name "*.gz" -o -name "*.zip" \) -mtime +30 -delete
Delete compressed log files older than 30 days
This command searches /var/log
for regular files that are either .gz
or .zip
AND were last modified more than 30 days ago, then deletes them. Use -delete
with caution!
find . -maxdepth 1 -type d \( -name "temp*" -o -name "cache*" \) -exec rm -rf {} +
Remove 'temp' or 'cache' directories in the current directory only
Here, find
looks only in the current directory (-maxdepth 1
) for directories (-type d
) named temp*
OR cache*
, and then removes them recursively. The -exec ... +
option is more efficient than -exec ... \;
for multiple files.