find 查找文件

find 查找文件

版权声明:原创文章,未经授权,请勿转载

find 是 Unix-like 操作系统中的一个命令行实用工具,可以用来查找、筛选指定的文件或目录,也可以指定过滤条件及行为,提供了很高的灵活度及便利。

find [path...] [expression]

find 搜索给定路径(path...)目录树上的每一个文件名,并从左至右计算给定的 表达式(expression),按照优先规则进行匹配,直到得出结果,然后 find 移向下一个文件名。
当所有文件都成功处理时 find 退出并返回状态值 0。如果发生错误则返回一个大于 0 的值。

表达式(expression)

表达式是由 选项测试动作 组成。以运算符分开,忽略运算符的时候,默认使用 -and 连接。如果表达式没有包含 -prune 以外的动作,当表达式为真时会执行 -print 动作。

  • 选项 指定执行测试动作时的一些选项,影响所有的操作,且总是返回真值。
  • 测试 在文件名上执行条件匹配,并返回匹配结果(一个真值或一个假值)。
  • 动作 在文件名上执行一个操作,并返回执行结果(一个真值或一个假值)。

连接运算符

( expr )
强制优先
! expr
-not expr
如果 expr 是 false 则返回 true
expr1 expr2
expr1 -a expr2
expr1 -and expr2
expr1 和 expr2 都为真时返回真。
expr1 -o expr2
expr1 -or expr2
expr1 或 expr2 其中之一为真时返回真。
expr1 , expr2
expr1 和 expr2 都会被执行。expr1 的值被忽略,结果值是 expr2的值。

常用选项

  • -follow
    不检索符号链接,含了 -noleaf

  • -maxdepth levels
    搜索给定路径(path...)的下层目录时,最深不超过levels(一个非负整数) 层。-maxdepth 0 意味着只在给定路径的目录中执行测试和动作。

  • -mindepth levels
    不在levels(一个非负整数)层之内执行任何测试和动作。-mindepth 1 意 味着处理所有的文件,除了命令行参数指定的目录中的文件。

  • -mount
    不进入处于其它文件系统之上的目录。可以用-xdev代替,从而和一些其他版本的 find 兼容。

常用测试(tests)

  • -name pattern
    匹配基本的文件名与 shell 模式 pattern 相匹配.

  • -iname pattern
    -name 类似,但是匹配时是不区分大小写的。

  • -path pattern
    文件名与 shell 模式 pattern 相匹配。元字符不会对 /. 做特殊处理。

  • -ipath pattern
    -path类似,但是匹配时是不区分大小写的。

  • -empty
    匹配文件是空的普通文件或者空目录

  • -readable
    匹配当前用户可读的文件。

  • -writable
    匹配当前用户可写的文件。

  • -perm mode
    匹配文件权限【刚好等于】mode的文件

  • -perm -mode
    匹配文件权限【完全包括】mode的文件

  • -perm /mode
    匹配文件权限【包含任意】mode的文件

  • -type c
    匹配文件是 c 类型的, 类型可取值如下:

    • b 特殊块文件(缓冲的)
    • c 特殊字符文件(不缓冲)
    • d 目录
    • p 命名管道 (FIFO)
    • f 普通文件
    • l 符号链接
    • s 套接字
    • D 门 (Solaris 特有)
  • 数字类型的参数可以指定 支持的参数: (-amin, -mtime, -gid, -inum, -links, -size, -uid, -used)

    • +n 是比 n 大,
    • -n 是比 n 小,
    • n 正好是 n 。
  • -size [cwbkMG]
    匹配文件大小, 依次是 字节数, 双字节的字, 512字节的块, kb, MB, GB。

  • -uid n
    用户的ID(UID in /etc/passwd)

  • -gid n
    组名的ID(GID in /etc/group)

  • -user name
    用户名

  • -group name
    组名

  • -nouser
    匹配文件拥有者不存在于 /etc/passwd 的文件

  • -nogroup
    匹配文件拥有组不存在于 /etc/group 的文件

  • -mtime n
    在之前n天【当天】被变更内容的文件

  • -mtime +n
    在n天之前【不含n天,过去到n天】被变更内容的文件

  • -mtime -n
    在n天之内【包含n天,n天到现在】被变更内容的文件

  • -newer file
    列出比file更新的文件

动作(action)

  • -delete
    • 删除文件或目录,如果移除成功,则为True。如果删除失败,则会打印错误消息,并且Find的退出状态将是非零的(当最终退出)。
    • 警告:
      • -delete 放在表达式的开头,将导致尝试删除 起始点 以下的所有内容。
      • -delete 操作将无法删除目录,除非它是空的。
  • -exec command
    执行 command;如果命令返回状态值0,那么 exec 返回true。所有 find 其余的命令行参数将作为提供给命令的参数,直到遇到一个由 ; 组成的参数为止。命令的参数中,字符串 {} 将以正在处理的文件名替换。
  • -print
    在标准输出打印文件全名,然后是一个换行符。(默认动作)
  • -print0
    在标准输出中打印出完整的文件名,然后是一个(null)空字符。这样可以正确地解释包含换行符或其他类型空格的文件名,以便程序能够正确处理find的输出。此选项与xargs-0选项相对应。
  • -printf format
    在标准输出打印 format 格式化后的内容。
  • -prune
    如果该文件是一个目录,则不进入该目录。如果指定了 -depth,则 -prune 不起作用。

例子

# 在/home/zero中查找空目录
find /home/zero -type d -empty

# 将当前目录下(包括子目录)所有dos格式的文件转换为unix格式
find . -type f -print0 | xargs -0 dos2unix --

# 删除/tmp目录下所有名为 core 的文件,前提是文件名中不存在 换行、单双引号,空格。
find /tmp -name core -type f -print | xargs /bin/rm -f

# 与上面相同,但更安全的版本
find /tmp -name core -type f -print0 | xargs -0 /bin/rm -f

# 为每个文件执行一个命令(大括号用单引号括起来,以防止它们被解释为shell脚本标点符号。分号同样受到反斜杠的保护)
find . -type f -exec file '{}' \;

# 忽略.git目录及其下的文件(小括号通过 '\' 转义, '*' 需要用引号扩起来, 否则会被 shell 处理为文件名)
find . ! \( -path '*/.git/*' -o -name '.git' \)

# 与上面相同,但更推荐的版本
find . -name .git -prune -o -print

# 列出当前目录下所有build目录(不包含./build)
# 条件: 是目录 and 不是 ./build and 名字是 build
find . -type d ! -path ./build -name build

# 列出./patchs下的文件夹(排除自己 ./patchs 与 子文件夹)
find ./patchs -type d ! -name patchs -prune

# xargs 调试方式
# -0: 输入以 \0 分隔
# -i: {} 替换为输入内容
find . -type d ! -path ./build -name build -print0 | xargs.exe -0 -i echo "dir: {}"
find . -type d ! -path ./build -name build -print0 | xargs.exe -0 -i echo "rm -rfi {}"

参考