find
— 查找文件
find
实用程序可用于搜索和对匹配给定一组条件的文件组执行命令。基本用法是 find path rules
。
为了可移植性,始终指定路径。不要依赖于 find
在未提供路径时默认为当前工作目录。
有用的规则包括
规则 | 效果 | POSIX? |
---|---|---|
-name "blah" |
仅查找名为 blah 的文件。可以使用 * 和 ? 通配符,但应像在 -name 'blah*' 中那样用引号括起来。 |
是 |
\! -name "blah" |
仅查找未命名为 blah 的文件。 |
是 |
-type f |
仅查找普通文件,而不是目录。 | 是 |
-type d |
仅查找目录。 | 是 |
-type l |
仅查找符号链接。 | 是 |
-user foo |
仅查找属于用户 foo 的文件。最好使用命名的用户而不是数字 UID。特别是,root 在某些系统上可能不是 UID 0。 |
是 |
-group foo |
仅查找属于组 foo 的文件。最好使用命名的组而不是数字 GID。 |
是 |
-maxdepth 3 |
仅向下深入子目录 3 级。 -maxdepth 1 将忽略指定路径的所有子目录。 |
否,GNU 和 BSD |
-mindepth 2 |
在匹配发生之前,忽略前 2 个目录级别。 -mindepth 1 将处理除命令行参数之外的所有文件。 |
否,GNU 和 BSD |
-exec foo '{}' |
执行命令。 {} 被当前匹配文件的名称替换。请参阅以下示例。 |
是 |
-execdir foo '{}' |
与 -exec 相同,但从匹配项的基目录中运行命令。 |
否,GNU 和 BSD |
-delete |
删除匹配项。 | 否,GNU 和 FBSD |
-print0 |
在输出中使用空字符而不是换行符分隔文件名。这对防止文件名中包含换行符的文件很有用。 | 否,GNU 和 FBSD |
注意:EAPI>=5 假设 GNU find,因此在 ebuild 上下文中为这些 EAPI 使用 GNU 扩展是安全的。
默认情况下,find
将用换行符分隔的文件列表回显到标准输出。它可以与一个 for
循环结合使用,用于少量文件,并且它们的名称中没有奇怪的字符和空格
for f in $(find "${S}" -type f) ; do
einfo "Doing unholy things to ${f}"
done
以上循环可能会导致名称中包含特殊字符的文件出现问题。更好的方法是在一个 while
循环中使用带有 -print0
选项的 find
(注意传递给 while
和 read
的选项用于更改分隔符)
while IFS="" read -d $'\0' -r f ; do
einfo "Calling down holy vengance upon ${f}"
done < <(find "${S}" -type f -print0)
作为替代方案,您可以使用 -exec
参数。请小心转义,以确保 bash
不会吞噬特殊字符
find "${S}" -name '*.data' -exec mv '{}' "${S}/data/" \;
当 -exec
被 ;
字符终止(需要转义或用引号括起来)时,命令行将为每个匹配项分别构建。如果它被 +
字符终止,则命令行将通过在末尾追加每个选定文件名来构建。
以下语法在您要运行的命令接受多个参数(例如 doins
)时很有用,并且在这种情况下效率更高
find "${S}" -name '*.so*' -exec doexe '{}' +
Find 还支持负匹配
find "${S}/bundled-libs" \! -name 'libbass.so' -delete
这将删除 “bundled-libs” 文件夹中的所有文件,除了 “libbass.so”。确保始终转义 !
字符,这样它就不会被 shell 解释。
警告:
-exec
参数存在安全问题,因为存在竞争条件(这也适用于 find . -print0 | xargs ...
结构)。在 ebuild 上下文中,这应该不是问题,因为目录通常不是随机用户可写的。但是,您应该考虑 -execdir
作为一种替代方法,它从匹配项的基目录中运行命令(注意 -execdir
不是 POSIX,请参阅表格)。有关更多详细信息和示例,请参阅 find(1)
和 IEEE Std 1003.1-2017-find。