Find 命令

 

Cheat sheets

仅查找第一层子目录内容,不处理第二层及以下子目录

find . -mindepth 2 -maxdepth 2

使用 -path 条件查找相对路径 . 目录下的 app.json 文件和子目录 conf 中的所有 json 文件

find . -maxdepth 2 -path './app.json' -o -path './conf/*.json'

使用 -path 条件查找绝对路径 /opt/foo 目录下的 app.json 文件和子目录 bar 下的所有 json 文件

find /opt/foo -maxdepth 2 -path '*/foo/app.json' -o -path '*/foo/bar/*.json'

查找修改时间在一天以内的文件

find . -mtime 0
# 或
find . -mtime -1

查找修改时间在两天以内的文件

find . -mtime -2

查找修改时间在一天以前的文件

find . -mtime +0

查找文件大小大于 10M 的文件,常用的大小后辍有

'b'    for 512-byte blocks (this is the default if no suffix is used)
'c'    for bytes
'w'    for two-byte words
'k'    for kibibytes (KiB, units of 1024 bytes)
'M'    for mebibytes (MiB, units of 1024 * 1024 = 1048576 bytes)
'G'    for gibibytes (GiB, units of 1024 * 1024 * 1024 = 1073741824 bytes)

The + and - prefixes signify greater than and less than

find . -size +10M

查找所有文本文件

find . -type f -exec grep -Il '' {} \; -print
# 或
find . -type f -print0 | xargs -0 grep -Il ''

在文本文件中查找匹配的模式

find . -type f -print0 | xargs -0 grep -I -i 'pattern'

其中,grep 命令的几个选项的解释所下

-I
忽略所有二进制文件

Process a binary file as if it did not contain matching data;
this is equivalent to the –binary-files=without-match option.

-L, --files-without-match
只打印不匹配模式的文件名

Suppress normal output; instead print the name of each input
file from which no output would normally have been printed.
The scanning will stop on the first match.

-l, --files-with-matches
只打印匹配模式的文件名

Suppress normal output; instead print the name of each input
file from which output would normally have been printed. The
scanning will stop on the first match.

Find 命令

find [staring-point...] [expression]

表达式 (Expression)

命令行中跟在 staring-point 后面的部分是 expression. 用来描述如何找到文件和处理文件. expression 包含以下内容:

  • 条件 (TEST)
    TEST 返回真或假,通常用在文件属性的判断上. 例如 -empty 条件只有当前目录为空时才会返回真.

  • 动作 (ACTIONS)
    ACTIONS 返回真或假,并带有副作用 (比如打印信息到标准输出). 例如 -print 动作将当前文件名打印到标准输出.

  • 全局选项 (GLOBAL OPTIONS)
    GLOBAL OPTIONS 会影响到命令行中所有的 testsactions. 例如 -depth 选项让命令以深度优先的方式遍历文件系统.

  • 位置选项 (POSITIONAL OPTIONS)
    POSITIONAL OPTIONS 只影响跟在其后的 testsactions. 例如 -regextype 选项只影响出现在该选项之后的正则表达式.

  • 操作符 (OPERATORS)
    OPERATORS 将表达式中各项组合起来. 例如 -o 代表逻辑或,-a 代表逻辑与. 如果没有指定操作符,将默认使用 -a.

POSITIONAL OPTIONS

  • -regextype <type>
    改变其后出现的 -regex-iregex 测试条件所使用的正则表达式语法。在命令行执行 find -regextype help 查看支持哪些正则表达式语法。

GLOBAL OPTIONS

  • -depth
    以深度优先的方式遍历文件系统,即优先处理目录下文件,然后再处理目录本身. -delete 操作隐含 -depth.

  • -maxdepth <level>
    从起始点开始最多向下搜索 level 层文件. -maxdepth 0 表示只对当前目录 . 执行 testaction. 执行 find . -maxdepth 0 只会得到 . 这一个结果。执行 find . -maxdepth 1 才会得到类似 ls 命令的结果。

  • -mindepth <level>
    不处理少于 level 层的文件. -mindepth 1 表示处理除了起始点外的所有文件.

如果需要查询子目录的内容,可以使用下面命令

find . -mindepth 2 -maxdepth 2

TEST

  • -name <pattern>
    file base name 进行模式匹配,文件名中不包含目录路径. 与 -name 匹配的文件名将永远不会包含斜杠(/),因此 -name a/b 将永远不匹配任何内容(需要使用-path)。要忽略目录及其下的文件,使用 -prune 而不是检查树中的每个文件。只支持 glob 格式的规则 *, ?, [], [^] (使用 man 7 glob 查看详细说明)。

  • -iname <pattern>
    -name 相同,大小写不敏感.

  • -path <pattern>
    对完整文件名(包含目录)进行模式匹配,不处理 /. 元字符。使用 -prune 忽略整个目录树,不去检查该目录树中的文件。注意,模式匹配测试从命令行上起点(start point)之一开始的整个文件名。只有起点是绝对路径,则在 -path 中使用绝对路径名才有意义。因此,下面的命令将永远不会匹配任何内容:

    find bar -path /foo/bar/myfile -print
    

    find 将 -path 参数与每个文件的 directory name + base name 进行比较。因此,文件名永远不会以斜杠(/)结尾,-path 参数以斜杠结尾将不匹配任何内容。

  • -ipath <pattern>
    -path 相同,但不区分大小写。

  • -regex <pattern>
    使用正则表达式来匹配完整文件名(包含目录)。

    # 查找当前目录下所有 yml 和 json 文件,跳过 node_modules 目录及其下文件
    find . -name 'node_modules' -prune -o -regextype egrep -regex '.*\.(yml|json)' -print
    
  • -iregex <pattern>
    -regex 相同,但不区分大小写。

  • -type <c>
    查找指定文件类型的文件,文件类型可以是 b - block,c - character,d - directory,p - named pipe,f - regular file,l - symbol link,s - socket.

  • -newerXY reference

    X|Y meaning
    a The access time of the file reference
    B The birth time of the file reference
    c The inode status change time of the file reference
    m The modification time of the file reference
    t reference is interpreted directly as a time

    查找所有 mtime 时间在 file.txt 文件的 mtime 之后的文件

    find . -newermm file.txt
    

    查找所有 mtime 时间在 2023-05-01 12:30 之后的文件

    find . -newermt '2023-05-01 12:30'
    

    -newermt given-date 表示 file-date given-date

    查找所有 mtime 时间在 2023-05-01 之后,但不超过 2023-05-02 的文件,也就是查找修改时间在 2023-05-01 的文件。

    find ./ -newermt "2023-05-01" ! -newermt '2023-05-02'
    
  • -mtime n

      means mtime description
    +n greater than n+1 ≤ mtime 文件的修改时间最少是 n+1 天前
    -n less than mtime < n 文件的修改时间在 n 天以内
    n exactly n ≤ mtime < n+1 文件的修改时间在过去的 n 和 n+1 天之间
    find . -mtime +0 # find files modified greater than 24 hours ago
    find . -mtime 0  # find files modified between now and 1 day ago
                    # (i.e., in the past 24 hours only)
    find . -mtime -1 # find files modified less than 1 day ago (SAME AS -mtime 0)
    find . -mtime 1  # find files modified between 24 and 48 hours ago
    find . -mtime +1 # find files modified more than 48 hours ago
    

ACTION

  • -delete
    删除文件,删除成功返回真,删除不成功则显示错误信息. 使用 -delete 会自动打开 -depth 选项.

  • -exec <command> [args …] ;
    执行 command 命令,命令返回0表示真. 所有 -exec <command> 之后的参数都被认为是命令行参数,直到 ; 作为参数出现. 参数中所有出现字符串 {} 的地方用当前正在处理的文件名替换. 这两个参数需要用 \ 转义或引号括起来以避免 shell 提前处理. 例如:

    # 查看当前目录及其子目录下所有文件的类型
    find . -type f -exec file \{} \;
    
    # 查看当前目录下所有文件的类型,不进入子目录
    find . -maxdepth 1 -exec file '{}' ';'
    
  • ok <command> [args …] ;
    -exec 命令相同,但执行命令需要用户确认.

  • -print
    打印完成整的文件名并换行。

    find 命令的默认行为是,对表达式为真的所有的文件执行 -print 操作,除非它包含除 -prune-exit 以外的其它 Action。这些 Action 禁止默认的 -print 操作,它们是 -delete, -exec, -execdir, -ok, -okdir, -fls, -fprint, -fprintf, -ls, -print and -printf

    下面两条命令的作用相同,打印表达式为真的所有文件名

    find . -name '.git*' -prune -o -type f
    
    find . \( -name '.git*' -prune -o -type f \) -print
    
  • -prune
    不进入所匹配目录,该目录下的文件不会被访问,返回真. find . -name '<pattern>' -prune -o \( ... -print0 \) 是一种常见组合。意思是 -prune 前面的表达式所匹配的目录不会被遍历,-prune 本身返回真,因此 -o 后面的表达式只会在未匹配的文件和未裁剪的目录上执行. -o 后面的括号是为了使表达式逻辑更清晰. 例如:

    查找当前目录下所有以 .git 开头的文件或目录,如果是目录则不访问该目录下的文件

    find . -name '.git*' -prune
    

    查找当前目录下所有不以 .git 开头的文件

    find . -name '.git*' -prune -o -type f -print
    

    与上面的命令结果相同,但会遍历文件名包含 .git 的目录下的内容,因此没有上面的命令效率高

    find . -path '*.git*' -o -type f -print
    

    与上面命令结果相同,也会遍历文件名包含 .git 的目录下的内容

    find . ! -path '*.git*'
    

OPERATORS

  • ( expr )
    明确优先级. 因为括号在 shell 中有特殊含义,通常需要将它们用引号括起来. 也可以用 \(...\) 的形式来替代 '(...)'.

  • !
    对 expr 取反. 通常也需要用 \! 来避免 shell 提前处理.

  • -not
    ! 相同,但不是 POSIX 兼容的.

  • expr1 expr2
    逻辑与. expr1 为假时不执行 expr2.

  • expr1 -a expr2
    expr1 expr2 相同.

  • expr1 -and expr2
    expr1 expr2 相同,但不是 POSIX 兼容的.

  • expr1 -o expr2
    逻辑或. expr1 为真时不执行 expr2.

  • expr1 -or expr2
    expr1 -o expr2 相同,但不是 POSIX 兼容的.

  • expr1, expr2
    expr1expr2 总是会被执行.