Linux FIND命令指南
1. 简介
Linux find 命令可用于查找磁盘上的文件和目录。它提供了几个命令行选项,使其成为一个强大的工具。在本教程中,我们将了解如何使用find命令。
2. 语法
让我们快速看一下find命令的基本语法:
find [path...] [expression]
path和expression都是可选的。
path参数指定一个或多个要搜索的目录。默认为当前工作目录。
expression参数决定输出中包含哪些文件和目录,以及对它们采取什么操作。默认是打印所有非隐藏文件和目录。
我们将在下一节中仔细研究表达式。
请注意,不同的 Linux 发行版和版本可能使用略有不同的语法或提供不同的选项。
3. 表达式
expression参数由选项、测试和操作组成。单个expression可以使用传统的布尔运算符(例如and和or )组合任意数量的这些。
让我们更详细地看一下其中的每一个。
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本身决定,而 -exec对find 的每个结果 执行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命令没有按预期工作。