2

关于 find 命令的15个超级有用的例子

 1 year ago
source link: https://www.51cto.com/article/721814.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

关于 find 命令的15个超级有用的例子

作者:刘光录 2022-11-02 08:32:46
本文我们会分享关于 find 命令的一些常见示例。不过在此之前,我们先来看一下它的语法,以及如何使用。
41348a877396700c945917be93b2ca2d42d076.jpg

find 命令用于在 Linux 命令行中搜索文件和目录。

find 是功能最强大、使用最频繁的命令之一,同时也是选项最多的命令之一,它有50多个选项,很容易让人弄混了,特别是当它与 exec 或 xargs 命令一起使用的时候。

作为系统管理员或者软件开发者,在命令行中工作时都不可避免的会使用到 find 命令。所以,与其畏难而逃避它,不如知难而进,拥抱它的力量。

本文我们会分享关于 find 命令的一些常见示例。不过在此之前,我们先来看一下它的语法,以及如何使用。

Linux 中的 find 命令

find 命令的一般语法为:

find [directory to search] [options] [expression]

方括号 [] 中所有的内容都是可选的,这意味着你可以在没有任何选项和参数的情况下运行 find 命令。不过这只会打印出当前路径下所有的文件和目录,这样没什么用处,对吧?

我们来详细了解一下它的参数。

  • directory to search:要搜索的目录,基本上就是我们要开始搜索的位置。默认情况下,搜索是递归的(也会搜索子目录),从当前位置开始;
  • options:选项,指定搜索的类型,可以按文件名称、文件类型、修改时间等(进行搜索),这里有50多个选项;
  • expression:指定的搜索词。如果是要按文件名查找,那么搜索词就是文件名;如果是要查找名称与表达式匹配的文件,那这里就用表达式。

看下面的例子:

find . -type f -name myfile

该命令将在当前目录及其子目录中进行搜索,查找名为 myfile 的文件(不是目录)。选项 -type f 表示只查找文件,单点 . 表示当前目录。

按名称查找文件和目录

可以按文件名搜索文件和目录:

find . -name SEARCH_NAME

由于没有指定文件类型,所以它会搜索具有给定名称的文件和目录。

下面的例子找到名为 mystuff 的文件和目录:

[gliu@fedora work]$ find -name mystuff./new/mystuff./mystuff

只查找文件或目录

如果只想查找文件,那么需要指定文件类型 -f:

find . -type f -name SEARCH_NAME

类型和名称的顺序无关紧要。上一个例子中,只查找文件,可使用如下命令:

[gliu@fedora work]$ find -type f -name mystuff./mystuff

如果只搜索目录,那么指定类型 -d:

find . -type d -name SEARCH_NAME

还是上面那个例子,如果只查找目录,使用如下命令:

[gliu@fedora work]$ find -type d -name mystuff./new/mystuff

执行不区分大小写的搜索

默认情况下,find 命令区分大小写。如果我们想要执行不区分大小写的搜索,可以使用 -iname 来代替 -name:

find . -type f -iname SEARCH_NAME

也可以将其与 -d 选项一起使用。

[gliu@fedora work]$ find -iname mystuff./new/mystuff./MyStuff./mystuff

按扩展名搜索(重要)

find 命令最常见的用法之一就是查找指定类型的文件,或者说是按照文件扩展名来进行查找。

比如,我们要在当前目录下搜索所有的 C++ 文件,而C++文件的扩展名是 .cpp,所以我们可以这样搜索:

find . -type f -name "*.cpp"

这样,我们告诉 find 命令查找类型为文件(file),并且以 .cpp 结尾的文件。

[gliu@fedora work]$ find . -type f -name "*.cpp"
./file.cpp
./.cargo/registry/src/github.com-1ecc6299db9ec823/libz-sys-1.1.3/src/zlib/contrib/iostream2/zstream_test.cpp
./.cargo/registry/src/github.com-1ecc6299db9ec823/libz-sys-1.1.3/src/zlib/contrib/iostream/test.cpp
./.cargo/registry/src/github.com-1ecc6299db9ec823/libz-sys-1.1.3/src/zlib/contrib/iostream/zf

注意:在使用 find 命令时,需要将表达式放在双引号中。

为什么要将表达式放在双引号中呢?因为如果要不这样做的话,shell会扩展通配符,将其替换为当前目录中所有以 .cpp 结尾的文件。

比如,假如当前目录下有两个文件:file1.cpp, file2.cpp,那么下面的命令:

find . -type f -name *.cpp

会被shell扩展为:

find . -type f -name file1.cpp file2.cpp

这种情况下,shell 就会给出提示:

find: paths must precede expression: 'file1.cpp'find: possible unquoted pattern after predicate '-name'?

另外,如果当前目录下只有一个扩展名为.cpp的文件,那就可以。

搜索多个扩展名(或条件)的多个文件

上述命令搜索给定扩展名的文件。那如果要同时搜索不同扩展名的文件,该怎么办呢?

可以使用逻辑或(OR) -o 来运行 find 命令:

find . -type f -name "*.cpp" -o -name "*.txt"

这样,就会搜索扩展名为 .cpp 或 .txt 的文件:

[gliu@fedora work]$ find . -type f -name "*.txt" -o -name "*.cpp"
./new.txt
./file.cpp
./new/new.txt
./new/dir2/another.txt
./new/dir1/new.txt
./another.txt

在指定目录中查找文件

我们上面的例子都是在当前目录中搜索,因为我们在命令中指定了 . 作为当前路径。

点 . 可以替换为绝对路径或者相对路径。这样我们就可以在不离开当前路径的情况下,在指定的目录中查找文件。

[gliu@fedora work]$ find ./new -name mystuff ./new/mystuff

在多个目录中搜索文件

如果你认为所要查找的文件可能位于多个位置,那么不必多次运行 find 命令,只需在 find 命令中指定要搜索的所有目录路径即可:

find ./location1 /second/location -type f -name "pattern"

查找空文件和目录

-empty 选项可以让你使用 find 命令查找空文件和目录。比如要查找当前路径下所有的空文件和目录,可使用如下命令:

find . -empty

也可以指定搜索的文件类型,只查找文件或者目录:

find . -empty -type f

还可以结合文件名使用:

find . -empty -type f -name "*.cpp"

查找大文件或小文件(根据文件大小搜索)

根据文件的大小执行搜索,可以查找大文件或者小文件。但这只适用于文件,不适用于目录。

要根据文件的大小搜索,可以使用 -size 选项,后面跟上一个值N(即文件的大小),+N 查找大于 N 的文件,-N 查找小于 N 的文件

比如,查找大小正好为 50KB 的文件:

find . -size 50k

在当前路径下查找大于 1G 的文件:

find . -size +1G

查找小于 20 bytes 的文件(注意单位是c而不是b):

find . -size -20c

要查找大于100 MB 但小于 2 GB 的文件:

find . -size +100M -size -2G

此外,还可以结合名称搜索。比如,要在根目录中查找以 .log 结尾,大于500MB的文件,可使用如下命令:

find / -size +500M -name "*.log"

关于文件大小值 N 的单位:

  • c : bytes(字节)
  • k: kilobytes(千字节)
  • M: Megabytes(兆字节)
  • G: Gigabytes(GB)

查找最近修改的文件(根据修改或创建时间搜索)

我们先来简单介绍下mtime, atime 和 ctime 的概念:

  • mtime:文件上次修改的时间;
  • ctime:文件创建的时间;
  • atime:文件上次访问的时间。

我们经常会有查找最近修改过的文件的需求,这时候,可以按修改时间来搜索文件。

比如,要查找 3天(3 * 24H)以内修改过的所有文件:

find . -type f -mtime -3

再比如,查找 5天以前创建的文件:

find . -type f -ctime +5

上述命令是以天为单位。那么,如果要搜索几分钟前修改过的文件呢?可以使用 mmin, amin 和 cmin。

比如,要查找 5分钟以内修改过的文件,可使用如下命令:

find . -type f -mmin -5

此外,还可以结合名称,指定时间的上限和下限进行搜索。比如,下面的命令将搜索过去20分钟到30分钟内,修改过的所有 .java 文件:

find . -type f -mmin +20 -mmin -30 -name "*.java"

查找具有特定文件权限的文件

find命令允许您搜索具有特定权限的文件。

find -perm mode

比如,在当前路径下查找所有权限模式为 777 的文件:

find . -perm 777

查找具有读写权限的文件(完全匹配,如果文件权限为 读写和执行,则不匹配):

find . -perm a=r+w

根据文件的所属用户查找

find 还可以根据文件的所有权进行搜索。

比如,在当前路径下搜索用户 John 所拥有的文件:

find . -type f -user John

当然,也可以与其他选项(比如文件大小,时间,名称等)结合使用:

find . -type f -user John -name "*.cpp"

不递归查找,仅在当前目录中搜索

默认情况下,find 命令在当前位置的所有子目录中搜索。如果不希望这样,可以将搜索深度指定为 1。这将限制搜索仅限于当前目录,不包括任何子目录。

find . -maxdepth 1 -type f -name "*.txt"
图片

从搜索中排除目录

如果要将某个目录从搜索中排除,可以结合 -path, -prune 和 -o 一起使用:

find . -path "./directory_exclude/*" -prune -o -name SEARCH_NAME

注意路径中的星号 *, -prune 选项在路径之后,-o 选项在 prune 之后。

基本上,prune命令要求不使用路径指定的值,它总是与 -o 一起使用,以确保 -o 的右侧只针对未被排除的目录。

处理 find 命令的输出结果(使用 exec 和 xargs)

到目前为止,我们介绍了关于find命令的一些标准查找文件的方法。此外,还可以通过对 find 命令的结果执行某些操作,来改进它。

例如,查找与特定名称模式匹配的文件并一次性重命名,或者查找空文件并删除。

我们知道,管道重定向可以用于将一个命令的输出与另一个命令输入相结合。但这对find命令的输出不起作用,至少不直接起作用。

如果要对find命令的结果执行操作,有两个选项,即 exec xargs

使用 find 和 exec

假如我们要对 find 的结果使用 ls -l 列出来,看下面的例子:

find . -type f -name "*.txt" -exec ls -l {} +

以下是输出:​

[gliu@fedora work]$ find . -type f -name "*.txt" -exec ls -l {} +
-rw-rw-r-- 1 gliu gliu 39 Oct 13 19:30 ./another.txt
-rw-rw-r-- 1 gliu gliu 35 Oct 13 15:36 ./new/dir1/new.txt
-rw-rw-r-- 1 gliu gliu 35 Oct 13 15:36 ./new/dir2/another.txt
-rw-rw-r-- 1 gliu gliu 35 Oct 13 18:51 ./new/mystuff/new.txt
-rwxrwxrwx 1 gliu gliu 35 Oct 13 15:37 ./new/new.txt
-rw-rw-r-- 1 gliu gliu 35 Oct 13 18:16 ./new.txt

不要忘记 exec 命令最后的 {} +,并且要注意 {} 和 + 之间的空格。

花括号 {} 引用 find 命令的结果,你可以将其认为是 {file1, file2, file3}。加号 + 用于终止 exec 命令。

exec 还有另一个约定:

find . -type f -name *.txt" -exec ls -l

上述命令中,分号 ; 用于代替加号 +,分号前面的反斜杠 \ 用于转义特殊字符。

{} + 的优点是它运行的命令更少,它就相当于是 ls -l file1 file2 file3;而 {} \ 则相当于运行 ls -l file1, ls -l file2, ls -l file3。

但是,{} \;具有在同一 exec 语句中多次使用 {} 的优点。例如,下面的命令将使用 .old 扩展名重命名所有找到的文件:

find . -type f -name *.txt" -exec mv {} {}.old

使用 xargs

许多 Linux 用户已经习惯了管道重定向。这个带有尾随 { }+ 的 exec 命令对他们来说似乎不太习惯。

这就是 xargs 命令存在的价值,你只需要通过管道将 find 命令的输出解析到 xargs 命令:

find . -type f -name *.txt" | xargs ls -l
图片

find 结合 grep 使用

上面我们介绍了 find 结合 exec 和 xargs 命令的使用,此外,还可以将 find 与 grep 命令一块使用。

对于任何系统管理员或软件开发人员来说,find 和 grep 是最常见且最有用的组合之一。

你可以使用 find 命令来查找文件,然后使用 grep 命令来搜索这些文件的内容。

比如,我们要搜索所有包含 “Alice”一词的 txt 文件,那么可以这样搜索:

find . -type f -name "*.txt" -exec

同样的,也可以使用 xargs 命令:

find . -type f -name "*.txt"
图片

当然,这是最简单的例子,如果你熟悉 grep 命令,可以根据自己的需求和喜好使用它。

find 命令的用法还有很多,我们列举了一些相对比较常用的。当你开始熟悉 find 命令的时候,就可以在各种情况下使用。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK