Linux 中的 find 命令简单介绍
在 Linux 系统上使用终端操作文件的过程中,总会遇到在某个文件夹下查找文件的情况,如查找文件名为 add.py 的文件、查找文件30分钟前生成的文件、批量删除文件夹下(包含子文件)文件名中没有符号 ‘G’ 的文件,等等。这些都需要我们通过一个搜索命令来完成。本篇介绍 Linux 中的 find 命令,它能够帮我们完成上面的类似任务。本篇以 Ubuntu 18.04 为例进行演示。
find 命令语法
find 命令的基本语法如下:
| 1 | find [路径] [参数] [命令] | 
- find 的对象是文件夹,且可以同时指定多个文件夹路径;当不指定文件夹路径时,默认为当前路径; 
- find 参数部分可以配置很多,下面重点介绍。当不指定参数时,默认时打印 - -print;
- 命令是可选参数,当需要直接对找到的文件或文件夹进行操作时,可以带上命令参数,一般命令参数都以 - {} \;结尾。
find 参数
find 参数是 find 强大功能的基础,通过配置不同的参数,可以使用 find 找到不同类型的文件或文件夹。
下面简单罗列一些常见的参数:
- -type 只显示指定类型的文件或文件夹; - 1 
 2
 3
 4
 5
 6
 7- f 普通文件 
 d 目录
 l 符号链接
 c 字符设备
 b 块设备
 s 套接字 socket
 p 具名贮列 Fifo- 1 
 2
 3
 4
 5
 6
 7
 8
 9- # 只查找当前目录(包含子目录,本篇默认都包含子目录)下的文件 
 find . -type f
 # 只查找当前目录下的子文件夹
 find . -type d
 # 只查看符号链接文件
 find . -type l
 # 把当前文件夹下(第一层)的所有软连接取消
 find . -maxdepth 1 -type l -exec unlink {} \;
- -name 文件名称符合 name 的文件; - 1 
 2
 3
 4
 5
 6
 7- # 查找当前目录中文件或文件夹名后面带 G 的 
 find . -name "*G"
 # 查找当前目录下文件或文件夹后面不带 G 的
 find . ! -name "*G"
 find . -not -name "*G"
 # 统计代码行数, grep -v ^$ 表示排除空行
 find . -name "topology.py" | xargs cat | grep -v ^$ | wc -l
- -iname 文件名称符合 name 的文件,但会忽略大小写; - 1 
 2- # 查找当前目录中文件或文件夹名后面带 G 或 g 的 
 find . -name "*g"
- -size 查找符合指定的文件大小的文件 - 1 
 2
 3
 4
 5
 6- c 字节 
 w 字(2字节)
 b 块(512字节)
 k 千字节(1024字节)
 M 兆字节(1024k字节)
 G 吉字节(1024M字节)- 1 
 2
 3
 4
 5
 6- # 查找大于10k的文件 
 find . -type f -size +10k
 # 查找小于10M的文件
 find . -type f -size -10M
 # 查找等于1G的文件
 find . -type f -size 1G
- -path 指定字符串作为寻找目录的范本样式;-ipath 忽略大小写; - 1 
 2
 3
 4- # 查找 /usr/ 目录下所有文件或文件夹路径中包含 'python' 的 
 find /usr/ -path "*python"
 # 忽略大小写
 find /usr/ -ipath "*python"
- -prune 排除指定字符串作为文件或文件夹的范本样式; - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18- # 在 /usr 目录下查找以 'py' 结尾的文件或文件夹,但排除文件夹 '/usr/local',即不在文件夹及其子文件夹下寻找 'py' 结尾的文件或文件夹 
 find /usr -path "/usr/local" -prune -o -name "*py"
 # 删除文件夹结尾为 'G' 的
 # {} 用于与 -exec 选项结合使用来匹配所有文件夹,然后会被替换为相应的文件夹名
 find . -name "*G" -type d -prune -exec rm -rf {} \;
 # 此处如果不带 '-prune',则虽然能够删除成功,却会报如下错误,注意 106G 为当前目录下的一个符合条件的文件夹
 # find: ‘./106G’: No such file or directory
 # 或者采用如下命令,但是,需要把 -depth 放在 -type 之前
 find . -name "*G" -depth -type d -exec rm -rf {} \;
 # 删除 jupyterlab 运行时产生的 .ipynb_checkpoints 隐藏文件夹,避免程序运行出问题。 假设所有项目文件在当前用户目录下
 rm -rf `find ~ -type d -name .ipynb_checkpoints`
 # or
 find ~ -type d -name ".ipynb_checkpoints" -prune -exec rm -rf {} \;
 # or
 find ~ -depth -type d -name ".ipynb_checkpoints" -exec rm -rf {} \;
- -atime 在过去 n 天内被读取过的文件或文件夹;-amin 在过去 n 分钟内被读取过的文件或文件夹; 
- -ctime 在过去 n 天内属性发生改变的文件或文件夹;-cmin 在过去 n 分钟内属性发生改变的文件或文件夹; 
- -mtime 在过去 n 天内内容发生改变的文件或文件夹;-mmin 在过去 n 分钟内内容发送改变的文件或文件夹; - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- # 过去 1 天内修改过的文件 
 find . -type f -mtime -1
 # 在过去 10 分钟内修改过的文件
 find . -type f -mmin -10
 # 在恰好 1 天前修改过的文件
 find . -type f -mtime 1
 # 在过去 1 天前修改过的文件
 find . -type f -mtime +1
 # 比文件 'test.log' 修改时间距离现在时刻更近的文件
 find . -type f -newer test.py
- -delete 删除文件; - 1 
 2- # 删除以 '.txt' 结尾的文件 
 find . -type f -name "*txt" -delete
- -perm 文件权限; - 1 
 2
 3
 4- # 文件权限是 600 的文件 
 find ~/.ssh -type f -perm 600
 # 文件其他组权限为 'r' 的文件
 find . -type f -perm -o=r
- -user 文件所有者; - 1 
 2- # 文件所有者为 admin 的文件 
 find . -type f -user admin
- -group 文件所属组; - 1 
 2- # 文件所属组为 admin 的文件 
 find . -type f -group admin
- -path 目录; - 1 
 2
 3
 4
 5
 6- # 查找 / 目录下文件大小超过1G的文件,同时排除 /mnt 目录 
 # 使用 ‘-path 目录路径 -prune -o’ 来排除指定的目录
 find / -path /mnt -prune -o -type f -size +1G
 # 如果有两个需要排除的目录
 find / -path /mnt -prune -o -path /root -prune -o -type f -size +1G
- -exec 执行命令; - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- # 切换文件所有者 
 find . -type f -user root -exec chown jinzhongxu {} \;
 # 删除以 '.txt' 结尾的文件,并提示是否删除,输入 yes 后删除
 find . -name "*.txt" -type f -ok -exec rm {} \;
 # 把一周前的 '.log' 文件移动到 bak 文件夹中
 find . -name "*.log" -type f -mtime +7 -exec cp {} bak \;
 # 把所有 '.log' 结尾的文件以 “LOG:文件名” 的形式打印出来
 find . -name "*.log" -type f -exec printf "LOG: %s\n" {} \;
 # 如果需要执行的命令比较多,可以先把命令写入一个脚本中,然后像下面这样执行
 find . -name "*.log" -type f -exec ./js.sh {} \;
 # 删除 mac 下自动生成的文件
 find . -name '__MACOSX' -prune -exec rm -rf {} \;
- -empty 文件内容为空的文件; - 1 
 2- find . -empty 
 find . -type f -size 0 -exec ls -l {} \;
- -depth 从指定的文件夹下最深层的子文件夹开始查找; - 1 
 2- # 从最深层子文件夹开始搜索 
 find . -depth -mmin -300
- -maxdepth 设置搜索的最大目录层级; 
- -mindepth 设置搜索的最小目录层级; - 1 
 2
 3
 4- # 只搜索当前文件夹第一层级的文件,即只搜索当前文件夹下的文件,而不搜索子文件夹 
 find . -maxdepth 1 -mmin -300
 # 只搜索当前文件夹第二层级及更深层级的文件,即只搜索当前文件夹下的子文件夹及其更深子文件夹下的文件
 find . -mindepth 2 -mmin -300
- 复杂运算式; - 复杂运算式,可以使用 - ()开将运算式分隔,然后使用下面的逻辑运算:- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- # 与 
 expr1 -and expr2
 # 非
 ! expr
 -not expr
 # 或
 expr1 -or expr2
 expr1, expr2
QA
- 使用命令时遇到权限不足会报错,影响判读: - 1 
 2- # 如下面的情况 
 find: ‘/disk0/lost+found’: Permission denied- 此时,我们能够把这些错误的提示筛选丢弃掉即可。即在原来的命令后面增加 - 2>/dev/null:- 1 
 2
 3
 4
 5
 6
 7
 8
 9- # 屏蔽所有错误信息 
 find /disk0 -name "*ironman*.mp4" -type f -print 2> /dev/null
 # or
 find /disk0 -name "*ironman*.mp4" -type f -print 2>/dev/null
 # or
 find /disk0 -name "*ironman*.mp4" -type f 2>/dev/null
 # 只屏蔽权限错误信息。速度慢
 find /disk0/ -name "*ironman*.mp4" -type f 2>&1 | grep -v "Permission denied"
- 不想在文件前有 - ./:- 1 - find . -name "*.py" - 此时,可以使用 - basename来帮助:- 1 
 2
 3
 4
 5
 6
 7
 8
 9- find . -name "*.py" -exec basename {} \; 
 find $(pwd) -name "*.py"
 find . -name "*.py" -exec realpath {} \;
 find . -name "*.py" -exec readlink -f {} \;
 # 或者扩展名 .py 也不要
 find . -name "*.py" -exec basename {} .py \;









