Contents

Linux FIND命令指南

1. 简介

Linux find 命令可用于查找磁盘上的文件和目录。它提供了几个命令行选项,使其成为一个强大的工具。在本教程中,我们将了解如何使用find命令。

2. 语法

让我们快速看一下find命令的基本语法:

find [path...] [expression]

pathexpression都是可选的。

path参数指定一个或多个要搜索的目录。默认为当前工作目录。

expression参数决定输出中包含哪些文件和目录,以及对它们采取什么操作。默认是打印所有非隐藏文件和目录。

我们将在下一节中仔细研究表达式。

请注意,不同的 Linux 发行版和版本可能使用略有不同的语法或提供不同的选项。

3. 表达式

expression参数由选项、测试和操作组成。单个expression可以使用传统的布尔运算符(例如andor )组合任意数量的这些。

让我们更详细地看一下其中的每一个。

3.1.选项

选项影响find的整体操作,而不是在搜索期间对特定文件的处理。

一些最重要的选项是:

  • -d , -depth:通过在目录本身中的文件之前处理子目录来执行深度优先遍历
  • -daystart:从一天开始而不是 24 小时前测量时间
  • *-help:*打印一个简单的命令行用法然后退出
  • -mindepth , -maxdepth : 控制停止前要搜索的目录级别(默认mindepth为 0,maxdepth默认为无限制)

3.2. 测试

测试是find命令的核心。**应用于找到的每个文件,**测试根据该特定文件是否通过而返回假。

我们可以使用测试来查看各种文件属性,例如修改时间、模式匹配、权限、大小等。让我们看看我们可以执行的一些更流行的测试。

首先,有按名称或类型匹配文件的测试:

  • -name:测试文件名是否匹配模式(使用简单的模式匹配并且只查看文件名)
  • -regex:测试文件名是否匹配模式(使用标准 Emacs 正则表达式并查看完整文件路径)
  • -type:测试文件是否为特定类型(常规文件、目录、符号链接等)

让我们使用find和*-name*测试来查找当前目录中的所有 XML 文件:

> find . -name "*.xml"
src/main/resources/applicationContext.xml
src/test/resources/applicationContext-test.xml

请注意,默认输出只是每个文件的完整路径。 现在,让我们只查找*/tmp*目录中的目录:

find /tmp -type d

还有几个测试可以使用时间比较来匹配文件

  • -amin-anewer-atime:根据相对时间或另一个文件测试文件的最后访问时间
  • -cmin-cnewer-ctime:根据相对时间或其他文件测试文件的创建时间
  • -mmin-mnewer-mtime:根据相对时间或另一个文件测试文件的修改时间
  • -newer:测试文件是否比另一个文件新

下面是一个示例find命令,它使用*–ctime在名为lib*的目录中查找过去一年创建的所有 JAR 文件:

find lib -name "*.jar" -ctime -365

或者我们可以在当前目录中找到比名为testfile的文件更新的所有文件:

find . -newer testfile

其他一些方便的测试可以根据其他文件属性(如权限或大小)进行匹配

  • -perm:测试文件权限是否匹配给定的权限模式
  • -size : 测试文件的大小

在这里,我们将使用*-perm*来查找当前目录中与权限模式 700 匹配的所有文件:

find . -perm 700

让我们使用*-size在名为properties*的目录中查找所有大于 1 KB 的文件:

find properties -size 1k

3.3. 行动

对匹配所有测试的文件执行操作。默认操作是简单地打印文件名和路径。

我们可以使用其他一些操作来打印有关匹配文件的更多详细信息

  • -ls:执行文件的标准目录列表
  • -print-print0-printf:将详细信息打印到标准输出
  • -fprint-fprint0-fprintf:将文件的详细信息打印到文件中

为了演示,让我们使用*-ls操作来执行target目录中所有.jar*文件的目录列表:

> find target -name "*.jar" -ls
4316430646    88112 -rw-r--r--    1 mike staff 45110374 Oct 14 15:01 target/app.jar

我们可以使用带有格式字符串的*-printf*来仅打印每行的文件大小和名称:

> find lib -name "*.jar" -printf '%s %p\n'
12345 file1.jar
24543 file2.jar

我们可以与find命令一起使用的一些更高级的操作是:

  • -delete:从磁盘中删除文件
  • -exec : 执行任意命令

假设我们要从*/tmp目录中删除所有.tmp*文件:

find /tmp -name "*.tmp" -delete

或者查找所有包含“interface”一词的*.java*文件:

find src -name "*.java" -type f -exec grep -l interface {} \;

注意“;” 最后。这会导致每次对每个文件执行一个grep命令(“\”是必需的,因为分号将由 shell 解释)。我们也可以使用“+”代替,这将导致多个文件同时传递到grep

-exec命令的替代方法 是将输出通过管道传输到 xargs xargs命令从标准输入中获取项目并在这些输入上执行给定的命令。让我们使用xargs重写上面的命令:

find src -name "*.java" -type f | xargs grep -l interface

虽然结果相同,但执行速度存在显着差异。让我们*time -exec *版本:

time find src -name "*.java" -type f -exec grep -l interface {} \;

返回:

8.39s user
20.43s system 
84% cpu 
34.048 total

现在,如果我们time使用 xargs

time find src -name "*.java" -type f | xargs grep -l interface

我们看:

find src -name "*.java" -type f 
0.13s user 
0.96s system 
70% cpu 
1.552 total
xargs grep -l interface
0.62s user 
0.42s system 
58% cpu 
1.794 total

使用xargs最终会快得多。速度的提高是因为 xargs基本上对一批输入进行操作,其大小由 xargs本身决定,而 -execfind 的每个结果 执行grep,一次一个。

3.4. 操作符

上述所有expression类型都可以使用传统的布尔运算符进行组合。

以下是受支持运算符的快速列表,按优先顺序排列:

  • (expr) : 括号强制在任何其他表达式之前执行里面的表达式;小心避免使用引号进行 shell 插值
  • !, -not:否定表达式;小心避免使用引号进行 shell 插值
  • -a , -and:对两个表达式执行布尔运算,仅当两个表达式都为真时才返回**真
  • -o , -or :对两个表达式执行布尔运算,如果任一表达式为真则返回**真

例如,我们可以在src目录中找到任何不是目录的文件:

find src ! -type d

或者我们可以在properties 目录中找到**所有带有.xml或*.yaml*扩展名**的文件:

find properties -name "*yaml" -o -name "*.xml"

4. 高级选项

除了路径和表达式之外,大多数版本的find都提供了更高级的选项:

find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path] [expressions]

首先,-H-L和*-P选项指定find命令如何处理符号链接*。默认使用*-P*,这意味着链接本身的文件信息将被测试使用。

-O选项用于指定查询优化级别。此参数更改find重新排序表达式的方式,以帮助在不更改输出的情况下加快命令速度。我们可以指定 0 到 3 之间的任何值(包括 0 到 3)。默认值为 1,这对于大多数用例来说已经足够了。

最后,-D选项指定了一个调试级别——它打印诊断信息,可以帮助我们诊断为什么find命令没有按预期工作。