BASH命令之乐(2)之find

继BASH命令之乐(1),继续BASH命令学习。。。

本篇文章介绍;

find命令

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

默认路径为当前目录;默认表达式为 -print

要列出当前目录及子目录下所有的文件和文件夹,采用如下写法:

$find base_path

例如;

find .  -print  #打印文件和目录列表

liujl@liujl-ThinkPad-Edge-E431:~/mybash$ find . -print
.
./ifs.sh
./debug1.sh
./find
./find/a
./out.txt
./hasNoLine.sh
./debug.sh
./success_test.sh
./sleep.sh

.指定当前目录, ..指定父目录

-print指定打印出匹配文件的文件名(路径)。使用'\n'用于分割文件名的界定符。

-print0 指明使用‘\0’用于分割文件名的界定符。


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

-name  按照文件名查找文件。

-iname 和-name类似,只是匹配名字的时候忽略大小写。

liujl@liujl-ThinkPad-Edge-E431:~/mybash$ find . -name "*.sh" -print
./ifs.sh
./debug1.sh
./hasNoLine.sh
./debug.sh
./success_test.sh
./sleep.sh
-iname参数

liujl@liujl-ThinkPad-Edge-E431:~/mybash/test$ ls
a.sh  b.pdf  c.exe  findtest.txt  FINDtest.txt  FINDTEST.txt
liujl@liujl-ThinkPad-Edge-E431:~/mybash/test$ find . -iname "find*.txt"
./FINDtest.txt
./FINDTEST.txt
./findtest.txt

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

liujl@liujl-ThinkPad-Edge-E431:~/mybash/test$ find . \( -name "*.sh" -o -name "*.pdf" \) -print
./a.sh
./b.pdf

注意:上例中\(和-name之间一定要有空格,同理“*.pdf”和\)之间也有空格。

-path可以使用通配符来匹配文件路径或者文件,-name总是用给定的文件名进行匹配。

-regex是基于正则表达式来匹配文件路径的。

下面匹配.pdf和.sh文件

liujl@liujl-ThinkPad-Edge-E431:~/mybash/test$ find . -regex ".*\(\.pdf\|\.sh\)$" -print
./a.sh
./b.pdf
说明:上面的正则表达式为任意字符(.)后跟0或者多个字符(*)并以.pdf和.sh结尾($)的文件。


否定参数 !

liujl@liujl-ThinkPad-Edge-E431:~/mybash/test$ find . ! -name "*.txt" -print
.
./c.exe
./a.sh
./b.pdf

find在使用时会遍历所有的子目录。因此可以采用一些深度参数来限制find命令遍历的深度:

-mindepth和-maxdepth,分别为限制find查找的最小深度和最大深度

liujl@liujl-ThinkPad-Edge-E431:~/mybash$ ls
debug1.sh  debug.sh  find  hasNoLine.sh  ifs.sh  out.txt  sleep.sh  success_test.sh  test
liujl@liujl-ThinkPad-Edge-E431:~/mybash$ find . -maxdepth 1 -type f -print
./ifs.sh
./debug1.sh
./out.txt
./hasNoLine.sh
./debug.sh
./success_test.sh
./sleep.sh
-maxdepth=2:

liujl@liujl-ThinkPad-Edge-E431:~/mybash$ find . -maxdepth 2 -type f -print
./ifs.sh
./debug1.sh
./find/a
./out.txt
./hasNoLine.sh
./test/FINDtest.txt
./test/c.exe
./test/FINDTEST.txt
./test/a.sh
./test/findtest.txt
./test/b.pdf
./debug.sh
./success_test.sh
./sleep.sh

说明 -type f,为搜索的类型为文件(file),下面会对此进行详细的介绍

根据文件类型搜索:

由于类UNIX系统将一切都视为文件,文件有不同的类型。

-type可以对文件进行过滤,通过此参数,我们可以为find的命令指定文件匹配的类型。

文件类型类型参数
普通文件f
符号文件l
目录d
字符设备c
块设备b
套接字s
fifop
liujl@liujl-ThinkPad-Edge-E431:~/mybash$ find . -type d -print
.
./find
./test

liujl@liujl-ThinkPad-Edge-E431:~/mybash$ find . -type f -print
./ifs.sh
./debug1.sh
./find/a
./out.txt
./hasNoLine.sh
./test/FINDtest.txt
./test/c.exe
./test/FINDTEST.txt
./test/a.sh
./test/findtest.txt
./test/b.pdf
./debug.sh
./success_test.sh
./sleep.sh

根据文件时间进行查找

三种文件时间如下:

-atime,访问时间,用户最近一次访问的时间

-mtime,修改时间,文件内容最后一次被修改的时间

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

下面举例中“-”表示小于,“+”表示大于

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

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

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

$find . -type f -atime 7 -print

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

$find . -type f -atime +7 -print
其他的-mtime和-ctime类似

-atime、-mtime和-ctime都是基于时间的参数,以“天”为单位,下面是以分钟为单位的时间参数:

-amin、-mmin和-cmin,操作和上文一致,不再赘述。

根据文件大小进行查找

-size

liujl@liujl-ThinkPad-Edge-E431:~/mybash$ find . -type f -size -2k
./ifs.sh
./debug1.sh
./find/a
./out.txt
./hasNoLine.sh
./test/FINDtest.txt
./test/c.exe
./test/FINDTEST.txt
./test/a.sh
./test/findtest.txt
./test/b.pdf
./debug.sh
./success_test.sh
./sleep.sh

查找当前目录下及子目录下类型为文件,大小小于2k的文件。

如果+2k,则查找大于2k的文件

除了k之外,还可以用其他单元:

b-----块(512字节)

c-----字节

w-----字(2字节)

k------千字节(1024个字节)

M-----兆字节

G------吉字节(1024M)


删除匹配的文件

-delete 删除find查找到的匹配的文件。

liujl@liujl-ThinkPad-Edge-E431:~/mybash/test$ ls
a.sh  b.pdf  c.exe  findtest.txt  FINDtest.txt  FINDTEST.txt
liujl@liujl-ThinkPad-Edge-E431:~/mybash/test$ find . -type f -name "*.txt" -print
./FINDtest.txt
./FINDTEST.txt
./findtest.txt
liujl@liujl-ThinkPad-Edge-E431:~/mybash/test$ find . -type f -name "*.txt" -delete
liujl@liujl-ThinkPad-Edge-E431:~/mybash/test$ find . -type f -name "*.txt" -print
liujl@liujl-ThinkPad-Edge-E431:~/mybash/test$ 

基于文件权限和文件所有权的搜索

-perm 文件权限

liujl@liujl-ThinkPad-Edge-E431:~/mybash/test$ ls -l
总用量 0
-rw-r--r-- 1 liujl liujl 0 12月 22 14:49 a.sh
-rw-r--r-- 1 liujl liujl 0 12月 22 14:49 b.pdf
-rw-r--r-- 1 liujl liujl 0 12月 22 14:50 c.exe
liujl@liujl-ThinkPad-Edge-E431:~/mybash/test$ find . -type f -perm 644 -print
./c.exe
./a.sh
./b.pdf

-user USER 能够找出由某个特定用户所拥有的文件,参数USER是用户名或者UID

打印出当前目录下liujl拥有的所有文件:

liujl@liujl-ThinkPad-Edge-E431:~/mybash/test$ find . -type f -user liujl -print
./c.exe
./a.sh
./b.pdf

使用exec或ok来执行shell命令

-exec:find命令对匹配的文件执行该参数所给出的shell命令。相应命令的形式为'command' { } \;,注意{ }和\;之间需要有一个空格。

-ok:和-exec的作用相同,只不过以一种更为安全的模式来执行该参数所给出的shell命令,在执行每一个命令之前,都会给出提示,让用户确定是否执行。

liujl@liujl-ThinkPad-Edge-E431:~/mybash$ find . -type f -exec ls -l {} \;
-rwxr-xr-x 1 liujl liujl 248 12月 21 10:00 ./ifs.sh
-rwxr-xr-x 1 liujl liujl 122 12月 21 08:51 ./debug1.sh
-rw-r--r-- 1 liujl liujl 0 12月 22 14:32 ./find/a
-rw-r--r-- 1 liujl liujl 87 12月 21 09:02 ./out.txt
-rw-r--r-- 1 liujl liujl 85 12月 21 22:09 ./hasNoLine.sh
-rw-r--r-- 1 liujl liujl 0 12月 22 14:50 ./test/c.exe
-rw-r--r-- 1 liujl liujl 0 12月 22 14:49 ./test/a.sh
-rw-r--r-- 1 liujl liujl 0 12月 22 14:49 ./test/b.pdf
-rwxr-xr-x 1 liujl liujl 100 12月 21 08:37 ./debug.sh
-rwxr-xr-x 1 liujl liujl 166 12月 21 09:01 ./success_test.sh
-rwxr-xr-x 1 liujl liujl 180 12月 21 08:30 ./sleep.sh

提醒:如果执行一些危险的操作,如rm、mv等,一定要确定find的内容是你需要执行操作的文件!!!,如果这种情况下,也最好用安全的操作方式-ok


liujl@liujl-ThinkPad-Edge-E431:~$ find . -name "*.conf" -mtime +5 -ok rm {} \;
< rm ... ./下载/linux-3.10/tools/perf/Documentation/asciidoc.conf > ?

liujl@liujl-ThinkPad-Edge-E431:~$ find . -name "*.conf" -mtime +5 -ok rm {} \;
< rm ... ./下载/linux-3.10/tools/perf/Documentation/asciidoc.conf > ? 

下面例子是查到文件后查找文件中是否存在指定字符串:(这个指令如果你不在root权限下,需要进入root 权限)

liujl@liujl-ThinkPad-Edge-E431:~$ sudo find /etc/ -name "passwd*" -exec grep "liujl" {} \;
[sudo] password for liujl: 
liujl:x:1000:1000:liujl,,,:/home/liujl:/bin/bash
liujl:x:1000:1000::/home/liujl:/bin/bash

-exec能够同print结合生成有用的输出信息。

liujl@liujl-ThinkPad-Edge-E431:~/mybash$ ls
debug1.sh  debug.sh  find  hasNoLine.sh  ifs.sh  out.txt  sleep.sh  success_test.sh  test
liujl@liujl-ThinkPad-Edge-E431:~/mybash$ find . -type f -name "*.sh" -exec printf "Text file: %s\n" {} \;
Text file: ./ifs.sh
Text file: ./debug1.sh
Text file: ./hasNoLine.sh
Text file: ./test/a.sh
Text file: ./debug.sh
Text file: ./success_test.sh
Text file: ./sleep.sh

让find跳过特定的目录

如果在查找文件时希望忽略某个目录,因为你知道那个目录中没有你所要查找的文件,那么可以使用-prune选项来指出需要忽略的目录。在使用 -prune选项时要当心,因为如果你同时使用了-depth选项,那么-prune选项就会被find命令忽略。

简单举例--不显示当前目录下的/test目录及其文件:

liujl@liujl-ThinkPad-Edge-E431:~/mybash$ ls
debug1.sh  debug.sh  find  hasNoLine.sh  ifs.sh  out.txt  sleep.sh  success_test.sh  test
liujl@liujl-ThinkPad-Edge-E431:~/mybash$ find . -path "./test" -prune -o -print
.
./ifs.sh
./debug1.sh
./find
./find/a
./out.txt
./hasNoLine.sh
./debug.sh
./success_test.sh
./sleep.sh

-path "./test" -prune -o -print 是 -path "./test" -a -prune -o -print 的简写表达式。

按顺序求值, -a 和 -o 都是短路求值,与 shell 的 && 和 || 类似。如果 -path  "./test" 为真,则求值 -prune , -prune 返回真,与逻辑表达式为真;否则不求值 -prune,与逻辑表达式为假。如果-path "./test" -a -prune 为假,则求值 -print ,-print返回真,或逻辑表达式为真;否则不求值-print,或逻辑表达式为真。
这个表达式组合特例可以用伪码写为
if -path "./test"  then
          -prune
else
          -print



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值