Linux 下搜索文件
通配符
通配符(wildcard)是 Bash 操作接口的一个功能。常用的通配符如下表:
符号 | 意义 |
---|---|
* | 代表 0 到无穷多个任意字符。 |
? | 代表一定有一个任意字符。 |
[] | 代表一定有一个括号内的字符,例如 [xgw] 代表可能是 xgw 其中一个。 |
[-] | 代表在编码顺序内的所有字符,例如 [0-9] 代表 0 到 9 之间的所有数字。 |
[^] | 第一个字符为 ^ 代表反向选择,例如 [^xpw]代表任意一个非 xpw 的字符。 |
快速搜索
在 Linux 中,可以使用不同的命令进行快速搜索,以下是一些常用命令。
使用 which
命令来查找命令所在路径。这个命令根据的是$PATH 环境变量所指定的路径去查询:
[root@101c7 ~]$ which ls
alias ls='ls --color=auto'
/usr/bin/ls
whereis
命令会在指定的几个常用目录中搜索文件,使用 -l
参数可以查看可搜索的目录。
whereis
命令可以搜索以下类型的文件:二进制文件(-b
)、说明文件(-m
)、源代码(-s
)和其他特殊文件(-u
)。
例如搜索和 ifconfig
有关的说明文档:
[root@101c7 audit]$ whereis -m ifconfig
ifconfig: /usr/share/man/man8/ifconfig.8.gz
locate
命令使用数据库来查找文件。数据库存放在 /var/lib/mlocate/
目录下,每天会更新一次。若需要手动更新数据库,可以使用 updatedb
命令。
例如忽略大小写搜索与 passwd
有关的文件,并列出前四个结果:
[root@101c7 audit]$ locate -i -l 4 passwd
/etc/passwd
/etc/passwd-
/etc/pam.d/passwd
/etc/security/opasswd
精确搜索
精确搜索指使用find
命令执行的搜索。
按时间搜索文件
与时间有关的参数有-atime
,-ctime
和-mtime
:
参数 | 说明 |
---|---|
-mtime n |
表示在 n 天之前那天内被更改过的文件; |
-mtime +n |
列出在 n 天之前(不含 n)被更改过的文件,文件修改日期大于等于 n+1 天; |
-mtime -n |
列出在 n 天之内(包含 n)被更改过的文件,文件修改日期小于等于 n 天; |
-newer file |
列出比file 还要新的文件名。 |
例如,搜索过去系统上 24 小时内有更改过的文件:
[root@101c7 ~]$ find / -mtime 0
/dev/char
/dev/char/189:132
查找当前目录下修改时间在 5 分钟到 24 小时之间的文件:
[root@101c7 ~]$ find -mtime 0 -mmin +5
.
./.bash_history
./audit
寻找/etc
目录下比/etc/passwd
文件日期新的文件:
[root@101c7 ~]$ find /etc -newer /etc/passwd | tail
/etc/audit/audit.rules
/etc/postfix
/etc/kernel
查找/root
目录下更改时间在 5 天前的文件并删除:
[root@101c7 audit]$ find /root -type f -mtime +5 -ok rm{} \;
删除当前目录中访问时间在 7 天以前,含有数字后缀的admin.log
文件:
[root@101c7 ~]$ find . -name "admin.log[0-9][0-9][0-9]" -atime -7 -exec rm {} \;
按用户名及组名搜索
可以使用 find
命令按照文件的所有者和用户组来搜索文件,常用参数如下:
参数 | 说明 |
---|---|
-uid n |
按照用户 UID 来搜索 |
-gid n |
按用户组 GID 来搜索 |
-user name |
按用户名来搜索 |
-group name |
按用户组名来搜索 |
-nouser |
搜索文件的所有者不存在 /etc/passwd 的人 |
-nogroup |
搜索所有用户组不存在 /etc/group 中的文件 |
例如查找 /home
目录下属于用户 abc 的文件:
[root@101c7 ~]$ find /home -user abc
查找系统中不属于任何人的文件:
[root@101c7 ~]$ find / -nouser
按文件名及属性搜索
主要参数:
参数 | 说明 |
---|---|
-name filename | 搜索文件名为 filename 的文件 |
-iname filename | 忽略大小写,搜索文件名为 filename 的文件 |
-size [±]SIZE | 搜索大小比 SIZE 大(+)或小(-)的文件,大小单位有 c、k、m、g 等 |
-type TYPE | 搜索文件类型为 TYPE 的文件,如一般文件(f)、设备文件(b、c)、目录(d)、连接(l)、socket(s)等 |
-perm mode | 搜索权限刚好等于 mode 的文件,如 mode 为 4775 |
-perm -mode | 搜索权限必须全部包括 mode 的权限,如 mode 为 0744,会找到权限为 4775 的文件 |
-perm +mode | 搜索权限包含任一 mode 的权限,如 mode 为 755 时,会找到权限为 101 的文件 |
例如,在当前目录中查找文件 redis-3.2.6.tar.gz 并删除:
[root@101c7 audit]$ find -name redis-3.2.6.tar.gz -delete
忽略大小写,在 /etc
目录下搜索 ssh 文件或目录:
[root@101c7 audit]$ find /etc -iname ssh
/etc/ssh
/etc/selinux/targeted/active/modules/100/ssh
在 /etc
目录中查找以 rc 开头的文件,并以列表形式显示:
[root@101c7 audit]$ find /etc -name rc* -ls
50332831 0 drwxr-xr-x 10 root root 127 Sep 7 05:53 /etc/rc.d
16781412 0 drwxr-xr-x 2 root root 45 Oct 13 2020 /etc/rc.d/rc0.d
33644238 0 drwxr-xr-x 2 root root 45 Oct 13 2020 /etc/rc.d/rc1.d
50332832 0 drwxr-xr-x 2 root root 45 Oct 13 2020 /etc/rc.d/rc2.d
在 /root
目录下搜索所有小于 1MB 的文件,用 -size -1M
参数等同于 -size 0M
,需要注意。这是个 ChatGPT 都会答错的问题:
[root@101c7 audit]$ find /root -size -1M
/root/audit/a.log
/root/3/3
查找 /root
目录下大于 10KB 并且(-a
表示“与”)小于 2M 的普通文件,并以列表形式显示:
[root@101c7 ~]$ find /root -type f -size +10k -a -size -2M -exec ls -lh {} \;
-rw-------. 1 root root 17K Sep 16 03:15 /root/.bash_history
-rw-------. 1 root root 178K Sep 9 05:48 /root/audit/b.log
-rw-r--r--. 1 root root 30K Sep 10 15:05 /root/backup/sdb4.dump
-rw-r--r--. 1 root root 11K Sep 10 14:39 /root/backup/lost.dump.bz2
查找当前目录中的所有目录并排序:
[root@101c7 ~]$ find . -type d | sort
.
./3
./audit
在当前目录下查找除普通文件以外的所有类型的文件:
[root@101c7 ~]$ find . ! -type f -print
.
./.pki
./.pki/nssdb
查找 /bin
和 /sbin
目录下中含有 SGID, SUID 或 SBIT 属性的文件:
[root@101c7 ~]$ find /bin /sbin -perm +7000
处理搜索结果
find
命令可以接受表达式,表达式可能由下列成份组成:操作符、选项、测试表达式以及动作。
常见动作有 -print
(打印输出,默认动作)、-ls
(显示长目录列表)、-delete
(删除文件)。
-exec
选项后面跟命令(不支持别名)或脚本,然后是大括号 {}
表示由 find
找到的路径名,一个空格,接 \
用来转义分号;表示命令结束。相应命令的形式为 command {} \
;
-ok
和 -exec
的作用相同,只不过在执行每一个命令之前都会给出提示,让用户来确定是否执行。
例如在 /etc
目录中搜索 passwd
文件并从中找 root
相关信息:
[root@101c7 audit]$ find /etc -name "passwd*" -exec grep "root" {} \;
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
在 /usr/sam
目录下查找不在 dir1
子目录之内的所有文件:
[root@101c7 ~]$ find /usr/sam -path "/usr/sam/dir1" -prune -o -print
复制搜索到的文件到 backup
目录下:
[root@101c7 ~]$ find . -type f -exec cp --parents {} ./backup/ \;
-exec
为每个文件生成一条单独的命令,例如搜索到 57 个文件,那么将生成 57 条单独命令。如果想要提高效率,可以使用 xargs
运行任何使用参数指定的命令,参数通过标准输入传递给程序。
例如配合 grep
在 find
找到的文件中搜寻特定内容:
[root@server1 ~]$ find /var -name *.log | xargs grep "notice"
/var/log/anaconda/X.log: (++) from command line, (!!) notice, (II) informational,
/var/log/anaconda/journal.log:Sep 22 13:09:41 localhost kernel: type=1107 audit(1632316181.830:44): pid=1577 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 msg='avc: received policyload notice (seqno=2)
将搜索到的文件重命名,可以在 xargs
中使用 {}
占位符来代表搜索结果:
[root@server1 ~]$ find . -name "back.sh*" | xargs -i mv {} {}.dele
[root@server1 ~]$ ll back*
-rwxr--r--. 1 root root 52 Oct 7 06:15 back.sh1.dele
-rwxr--r--. 2 root root 52 Sep 23 19:18 back.sh.dele