掌握Linux搜索文件的正确姿势

  • 原创
  • Madman
  • /
  • 2018-04-02 09:12
  • /
  • 0
  • 215 次阅读

Linux查找文件-min.png

Synopsis: which命令在PATH系统变量所指定的路径中搜索第一个匹配的结果,即查询某命令是否存在,它的具体执行路径是什么。whereis命令在/usr/bin或/usr/sbin等特定目录中查找文件。which和whereis都只是在指定目录中而非整个文件系统中查找文件,所以速度很快。locate则是在系统自动构建的索引数据库中模糊查找,当你记不清完整文件名时,使用locate查找很方便,缺点是索引并不是实时更新的。find命令可以指定精确的查询条件,比如模糊的文件名、文件类型、文件大小、文件权限、文件的时间戳、文件属主或属组、甚至还支持正则表达式,可以说是非常强大的搜索工具,缺点是速度较慢

1. which

which命令在PATH系统变量所指定的路径中搜索第一个匹配的结果,即查询某命令是否存在,它的具体执行路径是什么

# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

# which passwd
/usr/bin/passwd

2. whereis

whereis命令在/usr/bin/usr/sbin等特定目录(可用# whereis -l查看有哪些目录)中查找文件

# whereis passwd
passwd: /usr/bin/passwd /etc/passwd /usr/share/man/man1/passwd.1.gz /usr/share/man/man5/passwd.5.gz

# whereis -m passwd
passwd: /usr/share/man/man1/passwd.1.gz /usr/share/man/man5/passwd.5.gz

3. locate

如果当前系统存在大量的文件,更新全文件系统的索引数据库非常消耗系统资源,而更新是由cron周期性执行# updatedb,如果你想查找刚添加不久的文件可能没有查询结果,需要手动执行一次该命令,它会根据配置文件/etc/updatedb.conf去更新默认的索引数据库/var/lib/mlocate/mlocate.db

# touch newfile.data
# locate newfile
此时搜索不到结果

# updatedb
# locate *new?ile*
/root/newfile.data

常用选项与参数:

  • -i 忽略大小写的差异
  • -c 不输出文件名,仅计算找到的文件数量
  • -l 仅输出几行的意思,例如输出五行则是 -l 5
  • -S 输出 locate 所使用的数据库相关信息,包括文件和目录的数量等
  • -r 后面可接正则表达式的模式
1. 列出 locate 当前使用的信息库
# locate -S
Database /var/lib/mlocate/mlocate.db:
    10,472 directories
    99,482 files
    5,524,776 bytes in file names
    2,263,811 bytes used to store database

2. 查找文件名中包含 passwd 字符的文件,只显示5条记录
# locate -l 5 passwd
/etc/passwd
/etc/passwd-
/etc/pam.d/passwd
/etc/security/opasswd
/root/Python-3.5.2/Lib/test/keycert.passwd.pem

4. find

基本格式为# find [指定路径] [指定条件] [指定动作],默认会查找当前目录及子目录,默认动作是-print把结果输出到屏幕上

4.1 查询条件

(1) -name PATTERN 根据文件名查找

要查找的 PATTERN 基于shell 的 file globing 的匹配字符

  • ? 任意单个字符
  • * 任意长度任意字符
  • [set] 范围内任意字符
  • [^ set] [! set] 范围外任意字符
  • brace expansion 大括号扩展/tmp/{a,b,c}

-iname PATTERN 忽略字符大小写; -inode n 按inode号查找; -links n: 链接数为n的文件

查找当前目录及子目录下,所有以 .txt 结尾的文件
# find . -name '*.txt'

(2) -type [bcdpfls] 根据文件类型查找

  • b 块设备
  • c 字符设备
  • d 目录文件
  • p 命名管道
  • f 普通文件
  • l 符号链接
  • s 套接字文件
查找 /etc 目录及子目录下,名字包含 grub 的符号链接文件
# find /etc -type l -name '*grub*'

(3) -size N[bcwkMG] 根据文件大小查找

File uses n units of space. The following suffixes can be used:

  • b for 512-byte blocks (this is the default if no suffix is used)
  • c for bytes
  • w for two-byte words
  • k for Kilobytes (units of 1024 bytes)
  • M for Megabytes (units of 1048576 bytes)
  • G for Gigabytes (units of 1073741824 bytes)
默认单位是字节,这里的文件大小有一个单位的浮动,因为元数据的存在
-size -N : 查找大小为 N 个字节以下的文件[0, N-1]
-size N : 查找大小刚好等于 N 个字节的文件(N-1, N]
-size +N : 查找大小为 N 个字节以上的文件(N, +∞)

比如-size -5M代表[0, 4M], -size 5M代表(4M, 5M], -size +5M代表(5M, +∞)
查找当前目录及子目录下,文件大小大于10M的所有文件
# find . -size +10M

(4) -perm [-/]MODE 根据文件权限查找

  • -perm MODE 表示只有 属主、属组、其它人 三类用户的权限必须 完全等于 MODE指定的对应位置权限的文件才会匹配,例如,-perm 644则只能完全精确匹配 rw-r--r--,就算是 rwxrwxrwx也不能匹配
# ls -l
total 12
-rwxrwxrwx 1 root root 48 Sep  2 12:46 another_test.txt
-rw---x--- 1 root root 34 Sep  2 11:56 error.png
-rw-r--r-- 1 root root  0 Sep  2 16:14 my.sh
-rw---x--- 1 root root 23 Sep  2 11:53 test.txt

# find . -perm 644
./my.sh
  • -perm -MODE 表示只有 属主、属组、其它人 三类用户的权限必须完全等于或大于全部MODE指定的对应位置权限的文件才会匹配(三类用户的权限类似 '且' 关系) ,例如,-perm -664既可以匹配 rw-rw-r--,也可以匹配 rw-rw-rw-。但是像 rw-r--rw- 就不能匹配,因为属组权限不满足MODE中属组权限的要求
# ls -l
total 12
-rw-rw-r-- 1 root root 48 Sep  2 12:46 another_test.txt
-rw-r--rw- 1 root root 34 Sep  2 11:56 error.png
-rw-rw-rw- 1 root root  0 Sep  2 16:14 my.sh
-rw---x--- 1 root root 23 Sep  2 11:53 test.txt

# find . -perm -664
./another_test.txt
./my.sh
无法匹配 error.png
  • -perm /mode 表示只需 属主、属组、其它人 三类用户的权限任一类用户等于或大于 MODE指定的对应位置权限的文件就能匹配(三类用户的权限类似 '或' 关系) ,例如,-perm /222三类用户不管谁有写权限就匹配(或者这类用户只有写权限也行),所以可以匹配 rw---x---,也可以匹配 r--rw-r--。但是像 r--r--r-- 就不能匹配,因为没人有写权限w
# ls -l
total 12
-r----x--x 1 root root 48 Sep  2 12:46 another_test.txt
-rw---x--- 1 root root 34 Sep  2 11:56 error.png
-r----x--x 1 root root  0 Sep  2 16:14 my.sh
-rw---x--- 1 root root 23 Sep  2 11:53 test.txt

1. 属主有指定的 w 权限,虽然属组和其它人没有 w 权限,也可以匹配
# find . -perm /222
.
./test.txt
./error.png

2. 属主没有 x 权限,属组和其它人没有 w 权限,所以无匹配
# find . -perm /122
.

3. 属主没有 x 权限,属组没有 w 权限,但是其它人刚好有 x 权限,所以匹配到
# find . -perm /121
.
./another_test.txt
./my.sh 

示例:

1. 查找 /etc/init.d 目录下,所有用户都有执行权限且其它用户有写权限的文件
# find /etc/init.d/ -perm -113 

2. 查找 /etc 目录所有用户都没有写权限的文件,即 至少有一类用户有写权限(-perm /222)再取反
# find /etc/ -not -perm /222

3. 查找 /etc 目录下至少有一类用户没有写权限,即 所有用户都有写权限(-perm -222)再取反
# find /etc/ -not -perm -222

(5) -amin, -atime, -cmin, -ctime, -mmin, and -mtime 根据时间戳查找

想像一下时间线即可

  • -amin +N 查找从现在算起,过去的 N分钟以外 访问过的文件,比如现在是08:30, -amin +5表示查找在08:25之前访问过的文件
  • -amin N 查找从现在算起,过去的 刚好第N分钟 访问过的文件,比如现在是08:30, -amin 5表示查找在08:25访问过的文件
  • -amin -N 查找从现在算起,过去的 N分钟以内 访问过的文件,比如现在是08:30, -amin -5表示查找在08:25之后访问过的文件
  • -cmin N 文件状态被修改过的时间
  • -mmin N 文件数据被修改过的时间
  • -atime,-ctime,-mtime 精确到天
  • -mtime N 查找从现在算起,在N天之前的 24小时内 (即N当天)被修改过的文件,比如现在是8月15号,-mtime 5表示查找8月10号那一天被修改过的文件(注意: -mtime 0表示今天)
  • -mtime +N 查找从现在算起,在N天之前的 24小时内 (即N天之前)被修改过的文件,比如现在是8月15号,-mtime 5表示查找8月9号及之前被修改过的文件(注意: 不包括8月10号)
  • -mtime -N 查找从现在算起,在N天之前的 24小时内 (即N天之内)被修改过的文件,比如现在是8月15号,-mtime 5表示查找8月11号到今天之内被修改过的文件

-newer file: file为一个存在的文件,查找比 file 还要新的文件

1. 在/home目录下找出10天之前被修改过的文件
# find /home -mtime +10

2. 在/home目录下查找最近50天到100天之间修改过的文件
# find /home -mtime +50 –mtime -100

(6) 根据文件属主和属组查找

  • -uid N N为数字,这个数字是使用者的帐号 ID,亦即 UID ,这个 UID 是记录在/etc/passwd 里面与帐号名称对应的数字
  • -gid N N为数字,这个数字是群组名称的 ID,亦即 GID,这个 GID 记录在/etc/group
  • -user NAME NAME为使用者帐号名称喔!例如 dmtsai
  • -group NAME NAME为群组名称喔,例如 users
  • -nouser 查找文件的拥有者不存在于 /etc/passwd 的文件
  • -nogroup 查找文件的拥有群组不存在于 /etc/group 的文件

当你自行安装软件时,很可能该软件的属性当中并没有文件拥有者,这是可能的!在这个时候,就可以使用 -nouser-nogroup 查找

1. 查找 /etc 目录及子目录下,属于 nginx 用户的文件
# find /etc -user nginx

2. 查找系统中不属于任何用户的文件
# find / -nouser

(7) 组合条件查找

  • -a 与,同时满足
  • -o 或,满足一个即可
  • not ! 非,条件取反
-not A -a -not B = -not \(A -o B\)
-not A -o -not B = -not \(A -a B\)

查找 /etc 目录及子目录下,最近一周内其内容修改过的,且不属于用户 root 及 nginx 的文件
# find /etc -mtime 7 -not -user root -a -not -user nginx
# find /etc -mtime 7 -not \( -user root -o -user nginx \)

(8) 不深入子目录查找

1. 只查找当前目录,maxdepth选项要放在查找条件的第一位
# find . -maxdepth 1 -name '*.c'

2. 排除指定的子目录,查找/etc/下,除/etc/sane.d目录的其它所有.conf后缀的文件
# find /etc -path '/etc/sane.d' -prune -o -name '*.conf'

(9) 使用正则表达式

-regex 不像 -name 那样匹配文件名,而是匹配包括路径的完整文件名 /tmp/test.txt

需要在表达式前面加 .*.*/ ,有时候需要指定 -regextype sed|grep 使用哪种正则表达式才能查找到

# ls -l
total 3
-rw-r--r-- 1 root root    0 Jun 30 21:39 81397018-b84a-11e0-9d2a-001b77dc0bed.jpg
-rw-r--r-- 1 root root    0 Jun 30 21:39 foo-111.jpg
-rw-r--r-- 1 root root 1013 Jun 30 21:10 httpd.csr

# find . -regex "[a-f0-9\-]\{36\}\.jpg"    # 没查找到
# find . -regex ".*[a-f0-9\-]\{36\}\.jpg"    # 没查找到
# find . -regextype sed -regex ".*[a-f0-9\-]\{36\}\.jpg"    # 查找到
./81397018-b84a-11e0-9d2a-001b77dc0bed.jpg

4.2 处理动作

(1) -print

-print 动作是 find 的默认动作,将查找到的结果打印到屏幕上

查找 /tmp 目录及子目录下,包含 core 字符且为普通文件,并打印到屏幕上
# find /tmp -name core -type f -print 

(2) -exec COMMAND {} \;

  • -exec 代表 find 额外动作的开始
  • COMMAND 代表 find 命令的额外动作,
  • {} 代表 find 找到的内容,依次被传入给COMMAND处理
  • \; 代表 find 额外动作的结束,因为;在bash环境下有特殊意义,需要用反斜线转义
查找 /root/scripts 目录及子目录下,包含 start 字符且以 .sh 字符结尾的文件,并复制到 /tmp 目录中
# find /root/scripts -name '*start*.sh' -exec cp {} /tmp \;

-ok COMMAND {} \; 的效果类似,只是每次用COMMAND处理 find 的查找结果时会询问是否执行,更安全

find一次性查找符合条件的所有文件,并一同传递给给-exec或-ok后面指定的命令,但有些命令不能接受过长的参数,此时使用另一种方式: # find PATH EXPR1 EXPR2 | xargs COMMAND

1. 查找 /tmp 目录下,文件名含 core 的普通文件并删除
# find /tmp -name core -type f -print | xargs /bin/rm -f

2. 查找文件的内容包含 io 字符的普通文件
# find . -type f | xargs grep "io"

3. 查找文件名包含efi的文件,并拷贝到/tmp下
# find /mnt/cdrom/Packages/ -name '*efi*' | xargs -i cp {} /tmp

xargs默认将管道传递过来的字符添加加xargs后面的命令的末尾,如果想改变位置,需要使用-i选项

(3) 其它动作

  • -ls: 类似于对查找到的文件执行 ls -aldi 命令
  • -delete: 删除查找到的文件
分类: Linux
标签: find locate whereis which
未经允许不得转载: LIFE & SHARE - 王颜公子 » 掌握Linux搜索文件的正确姿势

分享

作者

作者头像

Madman

如果博文内容有误或其它任何问题,欢迎留言评论,我会尽快回复; 或者通过QQ、微信等联系我

0 条评论

暂时还没有评论.

发表评论前请先登录