find命令常用

find是UNIX/Linux命令行工具箱中最棒的工具之一。这个命令对编写shell脚本很有帮助。

find命令的工作方式如下:沿着文件层次结构向下遍历,匹配符合条件的文件,并执行相应的操作。


1.   根据文件名或正则表达式匹配搜索

选项-name的参数指定了文件名所必须匹配的字符串。我们可以将通配符最为参数使用。*.txt能够匹配所有的.txt结尾的文件名。选项-print在终端中打印符合条件(例如-name)的文件名或文件路径。

$find /home/obama  -name  ”*.txt”  -print

有个与-name相似的选项,-iname(忽略大小写)。

$ls

example.txt  EXAMPLE.txt file.txt

$find . –iname  “example*” –print

./example.txt

./EXAMPLE.txt

 

如果想匹配多个条件,可以采用OR条件操作:

$ls

new.txt some.jpg  text.pdf

$find   .    \( -name “*.txt”  -o -name  “*.pdf”  \)    –print

./text.pdf

./new.txt

\(以及\)用于将-name  “*.txt” -o  -name  “*.pdf”视为一个整体。

选项-path可以使用通配符来匹配文件路径或文件。

-name总是用给定的文件名进行匹配。-path则将文件路径最为一个整体进行匹配。

例如:

$find /home/users   -path  “*slynux*” -print

This will  match  files as  following  paths.

/home/users/list/slynux.txt

/home/users/slynux/eg.css

选项-regex的参数和-path类似,只不过-regex是基于正则表达式来匹配文件路径的。类似的-iregex用于忽略大小写。


2.   反选

find可以用”!”否定参数的含义。例如:

$ls

list.txt new.PY  new.txt  next.jpg test.py

$find .  !  -name  “*.txt”  -print

.

./next.jpg

./test.py

./new.PY

上面命令用于匹配所有不以.txt结尾的文件名。


3.   基于目录深度的搜索

find默认会遍历所有子目录。可以采用-maxdepth和-mindepth参数。

我们可以用-maxdepth参数指定最大深度。与此相似,可以指定一个最小深度,告诉find应该从此处开始向下查找,-mindepth参数设置最小深度。

$find .  –maxdepth  1 -type  f  -print

只列出当前目录下的普通文件。即使有子目录也不会被打印和遍历。

注意:如果-type放在–maxdepth前面,find会先找出符合-type的所有文件,然后在所有匹配的文件中在找出符合指定深度的那些。但是,如果先指定目录深度,在-type,那么find先找出符合指定深度的文件后,在按-type查找,这才是最有效的搜索顺序。


4.   用文件类型过滤

-type指定要搜索的目标文件类型。

只列出所有目录:

$find .  –type  d -print

将文件和目录分别列出不是个容易事。不过有find就好办了。只列出普通文件:

$find .  –type  f -print

只列出符号链接:

$find .  –type  l -print

文件类型

类型参数

普通文件

f

符号链接

l

目录

d

字符设备

c

块设备

b

套接字

s

FIFO

p

 


5.   根据文件时间进行搜索

UNIX/Linux文件系统中的每一个文件都有三种时间戳(timestamp),如下

l  访问时间(-atime):用户最近一次访问文件的时间

l  修改时间(-mtime):文件内容最后一次被修改的时间

l  变化时间(-ctime):文件元数据(metadata,例如权限或所有权)最后一次改变的时间

在UNIX中并没有所谓的“创建时间”的概念。

-atime、-mtime、-ctime可最为find的时间参数。它们可以整数值给出,单位是天。这些整数值通常还带有-或+:-表示小于,+表示大于,如下所示。

打印出在最近七天内被访问过的所有文件:

$find  .  –type f  -atime  -7 -print

打印出恰好在七天前被访问过的所有文件:

$find  .  –type f  -atime  7  -print

打印出访问时间超过七天的所有文件:

$find  .  –type f  -atime  +7 -print

-atime、-mtime、-ctime默认单位是“天”。还有一些基于时间的参数是以分钟作为计量单位的。

l  -amin

l  -mmin

l  -cmin

find另一个漂亮的特性是-newer参数。使用这个参数,可以指定一个用于比较时间戳的参考文件,然后找出比参考文件更新的(更长的修改时间)所有文件。

例如,找出比file.txt修改时间更长的所有文件:

$find  .  –type f  -newer  file.txt -print

find命令的时间戳操作选项对编写系统备份和维护脚本很有帮助。


6.   按文件大小搜索

$find .  –type  f -size  +2k

#大于2KB的文件

$find .  –type  f -size  -2kb

#小于2KB的文件

$find .  –type  f -size  2k

#大小等于2KB的文件

出来K之外,还可以用其他单位。

  b——块(512字节)

  c——字节

  w——字(2字节)

  k——千字节

  M——兆字节

  G——吉字节


7.   删除匹配文件

-delete可以用来删除find查找到的匹配文件。

删除当期目录下的所有.swp文件:

$find .  –type  f -name  “*.swp”  -delete


8.   按文件权限和所有权查找

文件匹配可以根据文件权限进行。列出具有特定权限的所有文件:

$find .  –type  f -perm  644  -print

#打印出权限为644的文件

可以用这种方法找出那些没有设置好执行权限的文件。

也可以根据文件的所有权进行搜索。用选项-user  USER就能找出某个特定用户有用的文件:

参数USER可以是用户名或UID

例如,打印出用户Obama拥有的所有文件:

$find .  –type  f -user  Obama  -print


9.   结合find,执行

find命令可以借助选项-exec与其他命令结合。-exec算是find最强大的特性之一。

将给定目录中的所有C程序文件拼接起来写入单个文件all_c_files.txt。我们可以用find找到所有的C文件,然后结合-exec使用cat命令:

$find .  –type  f -name  “*.c”  -exec cat  {} \; >all_c_files.txt

-exec之后可以接任何命令,对于任何一个匹配的文件名,{}会被该文件名所替换。例如find找到了两个文件test1.c和test2.c,那么那么cat {}将会执行cat test1.c和cat test2.c。

我们使用>操作符将来自find的数据流重定向到all_c_files.txt文件,没有使用>>(追加)的原因是因为find命令的全部输出只是一个单数据流(stdin),而只有当多个数据流被追加到单个文件时候才有必要使用>>。

无法在-exec参数中直接使用多个命令,它只能接受单个命令,不过我们可以耍个小花招。把多个命令写到一个shell脚本中(例如command.sh),然后子啊-exec中使用:-exec  ./command.sh {}  \;


10. 让find跳过特定的目录

为了提高性能,在搜索时,需要跳过一些目录,例如git为会为每个目录建立.git目录。因为版本控制目录对我们而言并没有什么用处,所以没有必要去搜索这些目录。

$find ./source_path  \(  -name  “.git”  -prune  \) -o  \(  -type f  -print  \)

这里,\(  -name  “.git”  -prune \)用于排除,\(  -type f  -print  \)

指明了需要执行的操作。这些动作需要放置在第二个语句块中。


11. 删除含有特殊字符的文件

比如删除,文件名的第一个字符是-的文件,使用rm删除的话,将优先会将文件名解释成选项,因为选项也是用-指定,man  rm,最后有说到使用:

rm --  -foo或rm -  ./-foo

另外这里,我们可以直接删除i节点的方法,删除该文件。

可以使用ls  -i与stat查看文件的inode,当然如果特殊字符正好是上述情况,第一个字符是-的话,使用ls与stat手动查看inode,需要./-foo。

找到inode号后使用-inum选项结合-delete,将含特殊字符的文件删除。

$find .  –inum  INODE_NUM -delete


12. 路径必须在表达式之前(paths must percede expression)

例如当前目录含有a.c、b.c、c.c

$find  .  -name *.c  -print

find: paths must percede expression

出现这种错误的原因,shell先将*.c扩展成a.c  b.c  c.c

相当于命令变成:

$find .  –name  a.c b.c  c.c  -print

这是种错误使用方式。取而代之,可以对*.c加上双引号:

$find .  –name  “*.c” -print

或者使用\,将\放在*前,避开该通配符。

$find .  –name  \*.c -print

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值