find 是一条递归命令,用于在一个目录中搜索符合条件的文件(或目录),然后对选定的文件执行某些操作。

find search_path selection_criteria action

Section 17.1: 按名称或扩展名搜索文件

查找与 pwd 相对的特定名称的文件/目录:

$ find . -name "myFile.txt"
./myFile.txt

要查找具有特定扩展名的文件/目录,请使用通配符:

$ find . -name "*.txt"
./myFile.txt
./myFile2.txt

要查找与许多扩展名之一匹配的文件/目录,可以使用通配符:

$ find . -name "*.txt" -o -name "*.sh"

查找名称以 abc 开头并以一个字母结尾的文件/目录:

$ find . -name "abc[a-z][0-9]"

查找特定目录下的所有文件/目录

$ find /opt

只搜索文件(不搜索目录),使用 -type f:

find /opt -type f

只搜索目录(不搜索普通文件),使用 -type d:

find /opt -type d

Section 17.2: 针对找到的文件执行命令

有时,我们需要针对大量文件运行命令。这可以使用 xargs 来完成。

find . -type d -print | xargs -r chmod 770

上述命令将递归查找相对于 .(即当前工作目录)的所有目录(-type d),并执行chmod 770。如果 find 没有找到任何文件,-r 选项会指定 xargs 不运行 chmod。

如果文件名或目录中有空格符,该命令可能会卡住;解决方法是使用下面的命令

find . -type d -print0 | xargs -r -0 chmod 770

在上例中,"-print0" 和 "-0" 选项会指定使用空字节分隔文件名,并允许在文件名中使用空格等特殊字符。这是 GNU 扩展,在其他版本的 find 和 xargs 中可能无法使用。

find . -type d -exec chmod 770 {} \;

在这里,"{}" 是一个占位符,表示你想在该处使用文件名。find 将对每个文件单独执行 chmod。

您也可以将所有文件名传递给 chmod 的单次调用,方法是使用

find . -type d -exec chmod 770 {} +

这也是上述 xargs 代码段的行为。(要单独调用每个文件,可以使用 xargs -n1)。

第三种方法是让 bash 循环查找文件列表中的输出:

find . -type d | while read -r d; do chmod 770 "$d"; done

这在语法上最是笨拙的使用,但当你想在每个找到的文件上运行多个命令时却很方便。

不过,面对名称奇特的文件名,这种方法并不安全。

find . -type f | while read -r d; do mv "$d" "${d// /_}"; done

上面的代码将用下划线替换文件名中的所有空格(如果前导目录名中有空格,此示例也不起作用)。

上述方法的问题在于,"while read -r" 希望每行一个条目,但文件名可能包含换行符(而且,“read -r ”会丢失任何尾部空白)。你可以通过回转来解决这个问题:

find . -type d -exec bash -c 'for f; do mv "$f" "${f// /_}"; done' _ {} +

这样,"-exec" 以完全正确和可移植的形式接收文件名;"bash -c" 则以若干参数的形式接收文件名,这些参数将在 "$@" 中找到,并正确地加上引号等(当然,脚本需要正确处理这些文件名;每个包含文件名的变量都需要加上双引号)。

神秘的 _ 是必要的,因为 bash -c 'script' 的第一个参数用于填充 $0。

Section 17.3: 按访问/修改时间查找文件

在 ext 文件系统中,每个文件都存储了与之相关的访问、修改和(状态)更改时间,要查看这些信息,可以使用 stat myFile.txt;使用 find 中的时间选项,我们可以搜索在特定时间范围内修改的文件。

要查找在过去 2 小时内修改过的文件,请执行以下操作

$ find . -mmin -120

查找最近 2 小时内未被修改的文件:

$ find . -mmin +120

The above example are searching only on the modified time - to search on access times, or changed times, use a, or c accordingly.

上述示例仅搜索 modified (修改)时间,如果要搜索 access (访问)时间或 changed (更改)时间,请相应使用 a 或 c 。

$ find . -amin -120
$ find . -cmin +120

格式如下:

  • -mmin n : 文件在 n 分钟前被修改
  • -mmin -n : 文件在少于 n 分钟前被修改
  • -mmin +n : 文件在 n 分钟前被修改过

查找最近 2 天内修改过的文件:

find . -mtime -2

查找最近 2 天内未修改的文件

find . -mtime +2

使用-atime和-ctime分别表示访问时间和状态更改时间。

格式如下:

-mtime n : 文件在 24 小时前被修改 -mtime -n : 文件在少于 24 小时前被修改 -mtime +n : 文件在 24 小时前被修改过

查找在 2007-06-07 至 2007-06-08 的 日期范围 内修改的文件:

find . -type f -newermt 2007-06-07 ! -newermt 2007-06-08

查找在一系列时间戳中访问过的文件(使用文件作为时间戳),从 1 小时前到 10 分钟前:

touch -t $(date -d '1 HOUR AGO' +%Y%m%d%H%M.%S) start_date
touch -t $(date -d '10 MINUTE AGO' +%Y%m%d%H%M.%S) end_date
timeout 10 find "$LOCAL_FOLDER" -newerat "start_date" ! -newerat "end_date" -print

格式如下:

-newerXY reference: 将当前文件的时间戳与 reference 进行比较。XY可以是以下值之一:at(访问时间)、mt(修改时间)、ct(更改时间)等。reference是要与指定时间戳(访问、修改、更改)进行比较的文件名或描述绝对时间的字符串。

Section 17.4: 根据大小查找文件

查找大于 15MB 的文件:

find -type f -size +15M

查找小于 12KB 的文件:

find -type f -size -12k

查找大小正好为 12KB 的文件:

find -type f -size 12k

Or

find -type f -size 12288c

Or

find -type f -size 24b

Or

find -type f -size 24

格式如下:

find [options] -size n[cwbkMG]

查找 n 块大小的文件,其中 +n 表示大于 n 块,-n 表示小于 n 块,n(不含任何符号)表示正好是 n 块

区块大小单位:

  1. c: bytes
  2. w: 2 bytes
  3. b: 512 bytes (default)
  4. k: 1 KB
  5. M: 1 MB
  6. G: 1 GB

Section 17.5: 过滤路径

-path 参数允许指定一个模式来匹配结果的路径。该模式也可以匹配名称本身。

只查找路径(文件夹或名称)中包含 log 的文件:

find . -type f -path '*log*'

只查找名为 log 的文件夹内的文件(任何含log的路径):

find . -type f -path '*/log/*'

只查找名为 log 或 data 的文件夹中的文件:

find . -type f -path '*/log/*' -o -path '*/data/*'

查找除名为 bin 的文件夹中的文件外的所有文件:

find . -type f -not -path '*/bin/*'

查找除 bin 文件夹或日志文件以外的所有文件:

find . -type f -not -path '*log' -not -path '*/bin/*'

Section 17.6: 按类型查找文件

要查找文件,请使用 -type f 标志

$ find . -type f

要查找目录,使用 -type d 标志

$ find . -type d

要查找块设备,使用 -type b 标志

$ find /dev -type b

要查找符号链接,使用 -type l 标志

$ find . -type l

Section 17.7: 按特定扩展名查找文件

要查找当前路径下所有具有特定扩展名的文件,可以使用下面的 find 语法。它通过使用 bash 内置的 glob 结构来匹配所有带有.extension的文件名。

find /directory/to/search -maxdepth 1 -type f -name "*.extension"

要查找当前目录中所有类型为.txt的文件,请执行

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