继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 |
fifo | p |
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