Linux 常用命令总结(二):find和grep命令


find和grep都是与文件和内容查找有关的命令,在linux中使用的频率非常高,是必须掌握的linux基础命令。


find

根据指定的规则(如文件名、文件类型、用户甚至是时间戳等),在一个目录树中搜索文件,并可以对搜索结果执行给定表达式。

常用形式

1
find [path...] [expression]

其中expression包含三类:options, tests, actions,还可以用operators进行逻辑运算。

options常用选项

  • -d -depth 查找/处理文件时按深度优先(先处理子文件夹的内容)
  • -maxdepth <level> (level为非负整数) 处理path目录时向下查找最多level级;例如-maxdepth 0表示仅查找/处理path目录而不管其子目录下的内容。
  • -mindepth <level> (level为非负整数) 对从path目录开始到向下level级目录不执行tests和actions;-mindepth 1表示处理除了path目录外的所有文件和子目录。

tests常用测试项

  • -name <pattern> 根据名称查找文件,pattern仅仅表示文件名,不能是路径(不能包含 '/');元字符('*', '?', '[]')可以匹配文件名开头的'.'
  • -path <pattern> 根据路径查找文件;pattern中的'/''.'不会特殊处理,正常匹配路径。
  • -regex <pattern> 根据路径的正则表达式查找文件。
  • -size <n>[cwbkMG] 根据大小查找文件,c表示bytes, w表示words, b表示blocks(512bytes),k表示kB, M表示MB, G表示GB。<n>都可以表示为+n,-n,n三种形式;+n 表示大于n,-n 表示小于n,n表示正好等于n。
  • -empty 可以匹配空文件和空目录
  • -type c 按文件类型查找,c通常取值为'f, d, l, s, p'。f表示普通文件,d表示文件夹,l表示符号链接,s表示socket文件, p表示管道文件。
  • -user <uname> 根据文件拥有者用户名(或ID)查找
  • -group <gname> 根据文件所属的用户组名(或ID)查找
  • 还有许多其他选项,可以根据文件的读写属性,访问权限,访问时间和修改时间,所在文件系统等等一系列条件来查找文件,这里就不一一列举了,具体请用man find查阅。

actions常用操作项

  • -delete 对匹配的文件进行删除,自动开启-depth模式。
  • -print 将查找的文件打印到标准输出;每个文件名后加一个newline字符('\n')。
  • -print0 将查找的文件打印到标准输出;每个文件名后加一个null字符('\0')。
  • -printf <format> 将查找的文件按format格式打印到标准输出;format格式类似C语言printf。
  • -fprint <file> | -fprint0 <file> | -fprintf <file> <format> 将查找的文件打印到file文件,file文件一定会被创建,其他跟print系列差不多。
  • -exec <cmd> ; 对每一个匹配的文件执行一次cmd命令(';'不可少);当前文件名将替换cmd中的每一个’{}’符号;(因为cmd在查找的启动目录中执行,不可避免的会有安全问题,man建议用-execdir而不用-exec)。
  • -exec <cmd> {} + 意义和上面一个差不多,不过找到的文件名参数传递给cmd的格式不一样;所有的文件名拼到一起传递给cmd,cmd调用次数更少,只能有一个'{}'符号。
  • -execdir <cmd> ; 安全版本的exec,cmd命令在当前匹配文件所在的目录中执行,可以有效避免race condition问题。
  • -execdir <cmd> {} + 同上
  • -ok cmd ; 和exec作用相同,只是每次执行命令前需要用户确认。

operators常用运算符

  • (expr) 小括号运算符表示运算优先级,因为小括号对于shell来说是特殊字符,所以需要转义并用引号引起来;如'\(...\)'
  • ! expr 表达式的值取反。
  • expr1 -a expr2 表达式and运算, -a是默认行为,可以省略。
  • expr1 -o expr2 表达式or运算。
  • expr1 , expr2 表达式并列运算,和一般的逗号运算符作用一样。

例子

1
2
3
4
5
6
7
8
// 删除当前目录中所有大小为0的文件。
$ find ./ -size 0 -exec rm {} \;

// 用ls -l列出当前目录下的所有普通文件。
$ find . -type f -exec ls -l {} \;

// 删除logs目录下所有修改时间在5天以前的文件。
$ find /logs -type f -mtime +5 -exec rm {} \;

find与xargs命令

xargs命令组合多个命令的工具,能够处理管道或者stdin并将其转换成特定的参数传递给其他命令。

find虽然有-exec动作选项执行命令,但有些系统对能够传递给exec的参数长度有限制,find命令将所有匹配到的文件一起传递给exec执行时,容易出现溢出错误,错误信息通常是“参数列太长”或“参数列溢出”,这时候就需要xargs出马解决问题。
另外,在有些系统中,使用-exec时每处理一个匹配到的文件就发起一个进程,这样在有些情况下就会出现进程过多,系统性能下降的问题。

使用xargs命令只有一个进程,而且可以分多次获取参数并执行命令,在获取参数时,一次获取参数的数目可以根据该命令的选项及系统内核中相应的可调参数来确定。

所以find命令通常都会跟xargs一起使用。下面是一些例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 查找系统中的每一个普通文件,然后使用xargs命令来测试它们分别属于哪类文件  
$ find . -type f -print | xargs file

// 在整个系统中查找内存信息转储文件(core dump) ,然后把结果保存到/tmp/core.log 文件中
$ find / -name "core" -print | xargs echo "" >/tmp/core.log

// 用grep命令在所有的普通文件中搜索hostname这个词
$ find . -type f -print | xargs grep "hostname"

// 删除3天以前的所有东西 (find . -ctime +3 -exec rm -rf {} \\;)
$ find ./ -mtime +3 -print|xargs rm -f –r

// 删除文件大小为零的文件
$ find ./ -size 0 | xargs rm -f &

grep

grep 是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。

常用形式

1
2
grep [OPTIONS] PATTERN [FILE...]  
grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]

常用选项

  • -i,--ignore-case 搜索时忽略大小写差别。
  • -c, --count 只打印匹配的行数,不显示匹配的内容。
  • -n,--line-number 打印匹配行时,在其前面打印行号。
  • -b, --byte-offset 打印匹配行时,在其前面打印匹配位置在文件中的字节位移(0 based byte offset)。
  • -<n> 同时显示匹配行上下的n行,如:grep -2 pattern a.txt同时显示匹配行的上下2行。
  • -f FILE 从文件中提取模板。空文件中包含0个模板,所以什么都不匹配。
  • -h,--no-filename 不打印匹配内容前面的文件名前缀;这是搜索单个文件时的默认行为。
  • -H,--with-filename 打印匹配内容前面的文件名前缀;这是搜索多个文件时的默认行为。
  • -l, --files-with-matches 不打印正常输出,只打印含有匹配内容的文件清单。
  • -L, --files-without-matches 不打印正常输出,只打印不含有匹配内容的文件清单。
  • -q, --quiet 不打印任何东西,只返回退出状态。状态为0则表示找到了匹配的行。
  • -s, --no-messages 不显示关于不存在或者无法读取文件的错误信息。
  • -v,--invert-match 反检索,只显示不匹配的行。

grep正则表达式基本元字符

模式 说明 例子
^ 锚定行的开始 如:'^grep'匹配所有以grep开头的行。
$ 锚定行的结束 如:'grep$'匹配所有以grep结尾的行。
. 匹配一个非换行符的字符 如:'gr.p'匹配gr后接一个任意字符,然后是p
* 匹配零个或多个先前字符 如:' *grep'匹配所有一个或多个空格后紧跟grep的行。 .*一起用代表任意字符。
[] 匹配一个指定范围内的字符 如:'[Gg]rep'匹配Grepgrep
[^] 匹配一个不在指定范围内的字符 如:'[^A-FH-Z]rep'匹配不包含A-FH-Z的一个字母开头,紧跟rep的行。
\(..\) 标记匹配字符 如:'\(love\)'love被标记为1
\&lt; 锚定单词的开始 如:'\&lt;grep'匹配包含以grep开头的单词的行。
\&gt; 锚定单词的结束 如:'grep\&gt;'匹配包含以grep结尾的单词的行。
x\{m\} 连续重复字符xm 如:'o\{5\}'匹配包含连续5个o的行。
x\{m,\} 连续重复字符x,至少m 如:'o\{5,\}'匹配至少连续有5个o的行。
x\{m,n\} 连续重复字符x,至少m次,不多于n 如:'o\{5,10\}'匹配连续5-10个o的行。
\w 匹配一个文字和数字字符,也就是[A-Za-z0-9] 如:'G\w*p'匹配以G后跟零个或多个文字或数字字符,然后是p
\W w的反置形式,匹配一个非单词字符 如:点号句号等。\W*则可匹配多个。
\b 单词锁定符 如: '\bgrep\b'只匹配grep,即只能是grep这个单词,两边均为空格。