深入理解 find 命令

目录

find 命令中有一些非常让人感到疑惑的地方包括-a -o -prune -print 等,这篇就详细分析一下。

规则

  先给出我们分析 find 命令的下面 4 个重要规则。

规则 1

1.在 find 命令中分为表达式和执行命令,默认的执行命令是-print,任何没有加-print 的 find 命令最后都会加一个-print,如果写的命令中有-print 则不会加这个-print

# 例如
find A -o B -a C 等于 find (A -o B -a C) -a -print (其中 A B C 都不是 -print)

规则 2

2.在表达式中是短路操作的。
也就是说表达式  A -o B  当 A=true 时不会执行 B,A -a B 当 A=false 时不会执行 B

规则 3

3. -a 的结合优先级大于 -o 

# 例如
A -o B -a C 等于 A -o (B -a C) 而不是 (A -o B) -a C

规则 4

4.-prune 的意思是不输出文件,并且返回为 true

实例分析

find nginx/logs \( -path '*txt' -o -name '*pid' \) -a -prune

#输出为
/nginx/logs/nginx.pid

# 分析
根据规则 1
因为整个命令中没有出现-print 所以我们需要在整个命令表达式后面加上 -print,也就是说命令变成下面这样

find /nginx/logs/  \( \( -path '*txt' -o  -name '*pid' \) -a -prune \) -a -print
                    ( (   A           -o   B            ) -a C       ) -a -print

当处理到 nginx.pid 文件时 A=false B=true 所以 ( A -o B ) = true ,然后执行-prune 这时不会输出 nginx.pid 但是 
( (( A -o B)) -a C ) = true  所以就会执行 -print 输出 nginx.pid



find nginx/logs \( -path '*txt' -o -name '*pid' \) -a -prune -o -print

#输出为
/nginx/logs/
/nginx/logs/nginx_access.log
/nginx/logs/nginx_error.log


# 分析
根据规则 1,命令中有-print,则我们不需要加上默认的-print 命令,整个命令还是保持原来的样子 


find /nginx/logs/   \( -path '*txt' -o  -name '*pid' \) -a -prune -o  -print
                     ( A            -o  B             ) -a C      -o  -print
又根据规则 3,命令变为下面的样子
find /nginx/logs/  \( \( -path '*txt' -o  -name '*pid' \) -a -prune \) -o  -print
                    ( ( A             -o  B             ) -a C       ) -o  -print

当遇到 nginx.pid 文件时, (A -o B) = true ,继续执行 C 这时不会输出 nginx.pid 并且 (((A -o B)) -a C) = true ,这时根据规则 2,所以不会执行-print
当遇到 nginx_error.log 文件时 (A -o B) = false ,根据规则 2 不会执行 C,((A -o B) -a C) = false,这时有根据规则 2,就会执行-print 命令,所以输出了 nginx_error.log


find nginx/logs \( -path '*txt' -o -name '*pid' \) -a -prune -o -type f

#输出为
/nginx/logs/
/nginx/logs/nginx_access.log
/nginx/logs/nginx_error.log
/nginx/logs/nginx.pid


# 分析

根据规则 1
因为整个命令中没有出现-print 所以我们需要在整个命令表达式后面加上 -print,也就是说命令变成下面这样

 find /nginx/logs/ \( \( \( -path '*txt' -o  -name '*pid' \) -a -prune \) -o -type f \) -a -print
                    (  (  ( A            -o  B             ) -a C       ) -o D        ) -a -print

当遇到 nginx.pid 文件时, ((A -o B) -a C) = true ,这时还不会输出 nginx.pid 直到 (((A -o B) -a C)) = true 所以执行 -print 命令输出了 nginx.pid
当遇到 nginx_error.log 文件时, ((A -o B) -C) = false 这时也不会输出,但是因为是文件,所以(((A -o B) -a C)) = true 所以执行了最后的-print


目录