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
7f 普通文件
d 目录
l 符号链接
c 字符设备
b 块设备
s 套接字 socket
p 具名贮列 Fifo1
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
6c 字节
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
2find . -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
9find . -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 \;