Iawen's Blog

我喜欢这样自由的随手涂鸦, 因为我喜欢风......

1. find命令

1.1 根据文件或者正则表达式进行匹配

列出当前目录及子目录下所有文件和文件夹

find .
find /home -name "*.txt"    #在/home目录下查找以.txt结尾的文件名
find /home -iname "*.txt"    #同上, 但忽略大小写

当前目录及子目录下查找所有以.txt和.pdf结尾的文件

find . \( -name "*.txt" -o -name "*.pdf" \)
find . -name "*.txt" -o -name "*.pdf"

匹配文件路径或者文件

find /usr/ -path "*local*"

基于正则表达式匹配文件路径
指定正则规则: -regextype posix-extended(type 类型包括 posix-awk, posix-basic, posix-egrep 和 posix-extended 四种, 默认的正则表达式类型是emacs)

find . -regex ".*\(\.txt\|\.pdf\)$"
find . -iregex ".*\(\.txt\|\.pdf\)$"    #同上, 但忽略大小写

1.2 否定参数

找出/home下不是以.txt结尾的文件

find /home ! -name "*.txt"

1.3 根据文件类型进行搜索

find . -type 类型参数

参数 类型
f 普通文件
l 符号连接
d 目录
c 字符设备
b 块设备
s 套接字
p Fifo

1.4 基于目录深度搜索

向下最大深度限制为3

find . -maxdepth 3 -type f

搜索出深度距离当前目录至少2个子目录的所有文件

find . -mindepth 2 -type f

1.5 根据文件时间戳进行搜索

find . -type f 时间戳

UNIX/Linux文件系统每个文件都有三种时间戳:

  • 访问时间(-atime/天, -amin/分钟): 用户最近一次访问时间。
  • 修改时间(-mtime/天, -mmin/分钟): 文件最后一次修改时间。
  • 变化时间(-ctime/天, -cmin/分钟): 文件数据元(例如权限等)最后一次修改时间。
# 搜索最近七天内被访问过的所有文件
find . -type f -atime -7

# 搜索恰好在七天前被访问过的所有文件
find . -type f -atime 7

# 搜索超过七天内被访问过的所有文件
find . -type f -atime +7

# 搜索访问时间超过10分钟的所有文件
find . -type f -amin +10

# 找出比file.log修改时间更长的所有文件
find . -type f -newer file.log

1.6 根据文件大小进行匹配

find . -type f -size 文件大小单元
文件大小单元:
b —— 块(512字节)
c —— 字节
w —— 字(2字节)
k —— 千字节
M —— 兆字节
G —— 吉字节

# 搜索大于10KB的文件
find . -type f -size +10k

# 搜索小于10KB的文件
find . -type f -size -10k

# 搜索等于10KB的文件
find . -type f -size 10k

# 要列出所有长度为零的文件
find . -empty

1.7 删除匹配文件

删除当前目录下所有.txt文件

find . -type f -name "*.txt" -delete

1.8 根据文件权限/所有权进行匹配

# 当前目录下搜索出权限为777的文件
find . -type f -perm 777

# 找出当前目录下权限不是644的php文件
find . -type f -name "*.php" ! -perm 644

# 找出当前目录用户tom拥有的所有文件
find . -type f -user tom

# 找出当前目录用户组sunk拥有的所有文件
find . -type f -group sunk

1.9 借助-exec选项与其他命令结合使用

# 找出当前目录下所有root的文件, 并把所有权更改为用户tom
find .-type f -user root -exec chown tom {} \;

# -ok和-exec行为一样, 不过它会给出提示, 是否执行相应的操作。
find $HOME/. -name "*.txt" -ok rm {} \;

# 查找当前目录下所有.txt文件并把他们拼接起来写入到all.txt文件中
find . -type f -name "*.txt" -exec cat {} \;> all.txt

# 将30天前的.log文件移动到old目录中
find . -type f -mtime +30 -name "*.log" -exec cp {} old \;

# 找出当前目录下所有.txt文件并以“File:文件名”的形式打印出来
find . -type f -name "*.txt" -exec printf "File: %s\n" {} \;

# 因为单行命令中-exec参数中无法使用多个命令, 以下方法可以实现在-exec之后接受多条命令
-exec ./text.sh {} \;

1.10 搜索但跳出指定的目录

查找当前目录或者子目录下所有.txt文件, 但是跳过子目录sk
find . -path “./sk” -prune -o -name “*.txt” -print

1.11 find 逻辑运算符

  • or
  • and
  • not
  • () 将测试和运算符组合在一起以形成更大的表达式。

2. grep命令

选项 说明
-R 递归地搜索包含指定字符串的文件
-E 使用扩展正则表达式
-w 只显示包含特定单词的行
-l 只输出文件名
-i 大小写不敏感
-n 显示指定字符串所在行的行号
-v 寻找不包含指定字符串的文件
–include
–exclude
搜索时包含/排除指定文件
–exclude-dir 排除指定目录

2.1 非递归搜索包含指定字符串的文件

第一个例子让我们来搜索 /etc/ 目录下所有包含 stretch 字符串的文件, 但不去搜索其中的子目录:

grep -s stretch /etc/*
/etc/os-release:PRETTY_NAME="Debian GNU/Linux 9 (stretch)"
/etc/os-release:VERSION="9 (stretch)"

​grep 的 -s 选项会在发现不存在或者不能读取的文件时隐藏报错信息。结果显示除了文件名之外, 还有包含请求字符串的行也被一起输出了。

2.2 POSIX字符类

字符类 说明
[:alnum:] 等同于: [A-Za-z0-9]
[:word:] 与 [:alnum:] 相同, 并带有下划线(_)字符
[:alpha:] 等同于[A-Za-z]
[:blank:] 包括空格和制表符
[:cntrl:] ASCII控制代码, 包括ASCII字符0到31和127。
[:digit:] 数字0-9
[:graph:] 可见字符, 在ASCII中它包含从33到126的字符。
[:lower:] 小写字母
[:upper:] 大写字母
[:punct:] 标点符号, 以ASCII表示, 相当于: [-!"#$%&’()*+,./:;<=>?@[\]_`{
[:print:] 可打印的字符, [:graph:]中的所有字符加上空格字符。
[:space:] 等同于: [ \t\r\n\v\f]
[:xdigit:] 用于表示十六进制数字的字符, 等同于[0-9A-Fa-f]

3. 快速搜索命令: which 和 locate

搜索文件的最简单的命令可能就是 which 和 locate 了, 但二者都有一些局限性。which 命令只会在系统定义的搜索路径中, 查找可执行的文件, 通常用于识别命令。如果您对输入 which 时会运行哪个命令感到好奇, 您可以使用命令 which which, 它会指出对应的可执行文件。

which which
/usr/bin/which

which 命令会显示它找到的第一个以相应名称命名的可执行文件(也就是使用该命令时将运行的那个文件), 然后停止。
locate 命令更大方一点, 它可以查找任意数量的文件, 但它也有一个限制: 仅当文件名被包含在由 updatedb 命令构建的数据库时才有效。该文件可能会存储在某个位置, 如 /var/lib/mlocate/mlocate.db, 但不能用 locate 以外的任何命令读取。这个文件的更新通常是通过每天通过 cron 运行的 updatedb 进行的。