linux中find相对路径_Linux搜索命令find和grep使用总结

前言

find和grep是Linux最基本的搜索命令,find用于搜索文件,grep用于搜索文件内容,熟练掌握其用法可以显著提高搜索效率,本文总结了两者的

常规用法

配合正则表达式使用

两者结合使用

配合shell脚本自定义搜索函数

1. find 基本用法

搜索包含res的文件

find "res"

结果中不仅会包含/res文件夹,也会包含res/strings.xml等文件

参数 -name 搜索仅匹配文件名而非相对路径

例:在当前路径搜索名称为strings.xml的所有文件

find ./ –name strings.xml

参数 -not 非

例:在当前路径搜索除了strings.xml文件外的所有文件

find ./ -not -name "strings.xml"

参数 -a 与

例:在当前路径搜索除了strings.xml文件外的所有xml文件

find ./ -not -name "strings.xml" -a -name "*.xml"

参数 -o 或

例:在当前路径搜索所有的xml和java文件

find . -name "*.xml" -o -name "*.java"

参数 -type 指定搜索的文件类型

例:在当前路径搜索所有文件夹

find . -type d

例:在当前路径搜索所有普通文件

find . -type f

2. grep 基本用法

在文件内搜索文件内容

例:在当前路径下的MainActivity.java文件中搜索onCreate方法

grep "onCreate" ./MainActivity.java

参数 -n 输出的结果打印行号

参数 -r 递归搜索

例:在当前目录以及子目录中搜索onCreate方法

grep -nr "onCreate"

使用-r参数后不需要加文件名

参数 -i 搜索忽略大小写

参数 -I 搜索结果只显示文件名

参数 -w 精确匹配结果

参数 -v 输出所有不匹配的行

3. find + 正则表达式(RE)

-name + RE 的使用

-name 是将文件名去匹配而不是文件的输出结果,以下为使用-name时的RE

符号

解释

*

代表任意字符(可以没有字符)

?

代表任意单个字符

[]

代表括号内的任意字符,[abc]可以匹配a\b\c某个字符

[a-z]

可以匹配a-z的某个字母

[A-Z]

可以匹配A-Z的某个字符

[0-9]

可以匹配0-9的某个数字

^

用在[]内的前缀表示不匹配[]中的字符

[^a-z]

表示不匹配a-z的某个字符

例1:在当前目录中搜素不以a、b、c开头的所有文件

find ./ –name “[^abc]*”

例2:在当前目录中搜索以大写字母或数字开头的所有文件

find ./ -name “[A-Z0-9]*”

-regex + RE 的使用

-regex 是将文件的输出结果进行匹配而不是文件名,使用-regex时必须使用正规的RE,以下为简单的RE使用

符号

解释

[]

代表括号内的任意字符,[abc]可以匹配a\b\c某个字符

[a-z]

可以匹配a-z的某个字母

[A-Z]

可以匹配A-Z的某个字符

[0-9]

可以匹配0-9的某个数字

.

表示任意单个字符

?

表示前面的字符出现一次或零次

+

表示前面的字符至少出现一次

*

表示前面的字符出现零次或多次

()

将字符括起来后面跟量词

|

逻辑或,可以搜索两个条件

例1:搜索所有输出结果包含res的文件(即使文件名不包含res,只要该文件在res文件夹中也都可以被搜索到)

find . –regex “.*res.*”

注意此时用的是.*而不是*去匹配任意字符

例:在当前目录搜索所有文件名末尾为res或res_ext的文件

find ./ -regex “.*res|.*res_ext”

4. grep + 正则表达式 (RE)

find中的RE使用均可使用,注意有些符号需要用\转义,其他常用符号如下

符号

解释

<

单词的开始

>

单词的结束

^

行的开始,^ 用在 [ ] 内表示不匹配其中的字符,注意区别

$

行的结束

{n}

表示前面的字符匹配n次

{n,m}

表示前面的字符匹配n-m次

{,m}

表示前面的字符至多匹配的m次

{n,}

表示前面的字符至少匹配n次

egrep

egrep是grep的进化版,改进了许多grep中不方便之处如下,egrep使用RE符号 + , ? , | (或) , {} 时不用转义,如果要用其本身则需要转义,因此推荐使用egrep和RE配合使用

例1:搜索精确匹配Dialer单词的行(形如DialerActivity则不会匹配)

egrep –nr “\”

例2:当前目录搜索以private开始的行(private前可能有空格)

egrep -nr "^.*private"

5. find和grep结合使用

面对大量代码时仅使用grep搜索会非常耗时,此时就需要将find和grep结合起来使用以提高搜索效率,先看一个例子

function jgrep()

{

find . -name .repo -prune -o -name .git -prune -o

-name out -prune -o -type f -name "*\.java" -print0 | xargs -0 grep --color -n "$@"

}

这个是Android系统源码build/envsetup.sh中的jgrep函数,用于搜索java文件内容,使用jgrep搜索效率远胜于单单使用grep进行搜索,下面对这个函数进行分析

find

在当前目录搜索

-o

或,并列多个条件

-name .repo –prune

忽略.repo目录(git库相关)

-name .git –prune

忽略.git目录(git库相关)

-name out –prune

忽略out目录(编译生成的目录)

-type f

指定文件类型为普通文件

-name "*.java"

指定匹配的文件名为.java文件

-print0 | xargs -0

忽略搜索中可能出现的错误信息,并将搜索到的文件作为结果向后传递并继续执行

grep --color –n

用grep在之前搜索到的文件中进行内容搜索,输出行号并标识颜色

"$@"

表示在使用jgrep函数时输入的参数,这里即为egrep搜索的内容

管道符号以及xargs的使用

上例中的|为管道符号,作用是将前一个命令的标准输出作为后一个命令的标准输入。

如果仅使用|,那么前面的结果会作为输入直接传递到后面的命令中,而使用xargs,就可以使前面的结果作为参数传递到后面的命令中,而这个特性对于find和grep而言十分重要。

例1:在当前目录中搜索所有AndroidManifest.xml文件并在其中搜索DialtactsActivity

find . –name AndroidManifest.xml | xargs grep –n –color “DialtactsActivity”

该例是xargs最基本的用法,如果将xargs去掉,那么grep搜索的内容是find输出的结果内容而非结果文件中的内容

例2:在当前目录搜索所有的values-zh-rCN文件目录并在其中搜索所有的strings.xml文件,然后在搜索到的strings.xml文件中搜索“通话”字符串

find . –type d –name “values-zh-rCN” |

xargs –i find {} –name “strings.xml” | xargs grep –n –-color 通话

该例中xargs后使用了-i参数,该参数的作用是可以将后面命令中的 {}符号视为前面find搜索的结果文件。本例中连续使用了两次xargs进行结果的传递

例3:在当前目录中的所有mk文件中搜索ro.build.type

find . –type f –name “*.mk” –print0 | xargs -0 grep –n –color “ro.build.type”

本例中和之前提到的jgrep函数都使用了–print0 | xargs -0进行结果传递而非单纯使用xargs,这样做的好处是如果find搜索会忽略可能出现的错误,使最终输出的结果更清晰,因此在使用xargs时建议按照–print0 | xargs -0方式书写命令

6. 编写搜索函数

find和grep的结合使用的命令较长,为方便起见,我们需要使用函数配合使用(形如上述的jgrep函数)。

下例中说明了如何编写搜索函数以及如何在Linux命令行中使用函数,这里可能需要用到简单的shell脚本命令:

编写简单的搜索函数

首先创建test.sh脚本文件并编写下述代码

function mkgrep()

{

find . -name .repo -prune -o -name .git -prune -o -name out -prune

-o -type f -name "*\.mk" -print0 | xargs -0 grep --color -n "$@"

}

函数的使用

#加载函数脚本,只需加载一次

source test.sh

#在当前目录及子目录下的所有.mk文件中搜索Dialer

mkgrep Dialer

编写复杂的搜索函数

首先创建test.sh脚本文件并编写下述代码

#文件内容搜索函数sep

#参数1 必选 搜索内容

#参数2 可选 前缀-t 内容所在的文件类型(即文件后缀名,如java),缺省为所有文件类型

#参数3 可选 前缀-f 指定搜索的目录 缺省为当前目录及所有子目录

#用例 sep "ITelecomService.Stub" -t java aidl -f packages/ frameworks/

#用例解析 在packages、frameworks目录中的所有java、aidl文件中搜索"ITelecomService.Stub"

function sep()

{

#文件内容=第一个参数

se_content=$1

#文件类型和搜索目录暂时=空

se_fileType=""

se_folder=""

#shift的作用是将第一个参数移除,即当前函数输入的第二个参数变成第一个参数,第三个变成第二个,以此类推

shift

#判断当前第一个参数是否为-t,即文件类型是否指定,如果指定就取出文件类型放入se_fileType变量中

if [ "$1" = "-t" ];then

#如果是-t就将这个参数移除

shift

while ( [ "$1" != "-f" ] && [ -n "$1" ] )

do

se_fileType="$se_fileType $1"

shift

done

fi

#判断当前第一个参数是否为-f,即搜索目录是否指定,如果指定就取出搜索目录放入se_folder变量中

if [ "$1" = "-f" ];then

#如果是-f就将这个参数移除

shift

while [ -n "$1" ]

do

se_folder="$se_folder $1"

shift

done

fi

#判断文件类型是否为空,不为空则建立循环分别搜索指定的文件类型

if [ -z $se_fileType ];then

#这里如果搜索目录为空find会自动搜索当前目录及子目录,因此不用再做判断

#这里用到了egrep而不是grep,方便输入搜索内容时直接使用正则表达式

find $se_folder -type f -print0 | xargs -0 egrep -n --color "$se_content"

else

for ft in $se_fileType

do

find $se_folder -type f -name "*.$ft" -print0 | xargs -0 egrep -n --color "$se_content"

done

fi

}

函数的使用

#加载函数脚本,只需加载一次

source sep.sh

#在当前路径下的packages、frameworks目录中的所有.java和.aidl文件中搜索ITelecomService.Stub

sep "ITelecomService.Stub" -t java aidl -f packages/ frameworks/

你可能感兴趣的:(linux中find相对路径)