find 查找文件
功能:在文件树中查找文件,并作出相应的处理。find命令可以遍历当前目录甚至于整个文件系统来查找某些文件或目录。find命令在网络文件系统(NFS)中同样有效。
普通用户只能查找自己的拥有的文件,不能查找其他用户的文件;根用户能查找全部文件。
find命令是直接读取磁盘文件,然后在其中寻找相应的文件。这种寻找方式比较慢,但该命令提供了丰富的选项功能,弥补了这点遗憾。
find命令可以根据权限、时间信息、大小等各种信息查找文件。找到文件后,find命令还可以调用其他shell命令进行后续操作。NFS:
网络文件系统,英文Network File System。是一种在网络上的机器间共享文件的方法,文件就如同位于客户的本地硬盘驱动器上一样。它可以把文件系统导出给其它系统,也可以挂载从其它机器上导入的文件系统。NFS最大功能就是可以通过网络让不同的机器,不同的操作系统彼此共享文件(sharefiles)——可以通过NFS挂载远程主机的目录,访问该目录就像访问本地目录一样。一般而言,使用NFS服务能够方便地使各unix-like系统之间实现共享,但如果需要在unix-like和windows系统之间共享,那就得使用samba了。Unix-like即类UNIX系统:
类Unix系统(英文:Unix-like)指各种传统的Unix系统(比如FreeBSD、OpenBSD、SUN公司的Solaris)以及各种与传统Unix类似的系统(例如Minix、Linux、QNX等)。它们虽然有的是自由软件,有的是商业软件,但都相当程度地继承了原始UNIX的特性,有许多相似处,并且都在一定程度上遵守POSIX规范。用法:find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
处理符号连接
- -H:表示只跟随命令行中指定的符号连接。
- -L:表示跟随所有的符号连接。
- -P:表示不跟随符号连接。是默认的选项。
当前目录下有一个符号连接e1000,现在我想查找文件名中最后一个字母是数字的源文件# find -H e1000 . -name "*[0-9].c" -print使用H选项,也查询e1000文件夹的文件# find -L . -name "*[0-9].c" -print使用L选项,也可以查找# find -P . -name "*[0-9].c" -print使用P选项,仅仅查询当前目录下。不搜索符号链接文件# find . -name "*[0-9].c" -print默认使用了P选项,仅仅查询当前目录下。不搜索符号链接文件路径(path...)
find命令所查找的目录路径。例如用.(点号)来表示当前目录,用/(斜杠)来表示系统根目录。默认路径为当前目录。
表达式(expression)
表达式可能由下列成份组成:设置项(option)、测试表达式(test)、动作项(action),这三类又可以通过逻辑运算符(operator)组合在一起形成更大更复杂的表达式。正是[expression]部分的丰富,才使得find如此强大。默认表达式为 -print
操作符
未做任何指定时默认使用 -and 。下列操作符,优先级递减:
- ! EXPR
- -not EXPR
- EXPR1 -a EXPR2
- EXPR1 -and EXPR2
- EXPR1 -o EXPR2
- EXPR1 -or EXPR2
- EXPR1 , EXPR2
设置项(option)
针对这次查找任务,而不是仅仅针对某一个文件,设置项总是返回true。
位置选项(总是真):
- -daystart:从当日起始时开始而不是从24小时之前,计算时间(for -amin, -atime, -cmin, -ctime, -mmin, and -mtime)。
- -follow:如果find命令遇到符号链接文件,就跟踪至链接所指向的文件。
- -regextype:指定“type”类型的正则语法,find支持的正则语法有:emacs、posix-awk、posix-basic、posix-egrep、posix-extended。find使用posix-extened正则:
find . -regextype posix-extended -regex ".*\.(txt|sh)"
普通选项(总是真,在其它表达式前指定):
- -depth:使用深度级别的查找过程方式,在某层指定目录中优先查找文件内容。
- -maxdepth LEVELS:表示至多查找到开始目录的第level层子目录。level是一个非负数,如果level是0的话表示仅在当前目录中查找。
- -mindepth LEVELS:表示至少查找到开始目录的第level层子目录。
- -mount:不跨越文件系统的mount点,即在当前的文件系统查询,不进入其他文件系统(如挂载的windows系统)。不在其它文件系统(如Msdos、Vfat等)的目录和文件中查找。
- -noleaf:
- -xdev:
- -ignore_readdir_race:
- -noignore_readdir_race:
测试表达式(test)
测试表达式是匹配表达式,是find命令接受的表达式,find命令的所有操作都是针对表达式的。
-amin N 查找系统中最后N分钟访问的文件 -anewer FILE 对文件的最近一次访问比 file 修改时间要晚。如果命令行中 -follow 在 -anewer 之前,(也只有在这种情况下 -anewer会受 -follow 的影响)。 -atime N 查找系统中最后n*24小时访问的文件 -cmin 查找系统中最后N分钟被改变文件状态的文件 -cnewer 文件 对文件状态的最近一次修改比 file 修改时间要晚。如果命令行中 -follow 在 -cnewer 之前,(也只有在这种情况下-cnewer 会受 -follow 的影响)。 -ctime N 查找系统中最后n*24小时被改变文件状态的文件 -empty -false -fstype 类型 查找位于某一类型文件系统中的文件,这些文件系统类型通常可以在配置文件/etc/fstab中找到,该配置文件中包含了本系统中有关文件系统的信息。 -gid N -group 名称 按照文件所属的组来查找文件 -ilname 匹配模式 -iname 匹配模式 该选项的作用和-name类似,不过匹配的时候忽略名字的大小写。 -inum N -ipath 匹配模式 -iregex 匹配模式 -links N -lname 匹配模式 -mmin N 查找系统中最后N分钟被改变文件数据的文件 -mtime N 查找系统中最后n*24小时被改变文件数据的文件。按照文件的更改时间来查找文件,-n表示文件更改时间距现在n天以内,+n表示文件更改时间距现在n天以前。
find命令还有-atime和-ctime选项,但它们都和-mtime选项相似,所以我们在这里只介绍-mtime选项。-name 匹配模式 按照文件名查找文件。支持统配符*和?。 -newer 文件 按着更改时间 比如:file1 ! file2 查找更改时间比文件file1新但比文件file2旧的文件 -nouser 查找无有效属主的文件,即该文件的属主在/etc/password中不存在 -nogroup 查找无有效所属组的文件,即该文件所属的组在/etc/groups中不存在 -path 匹配模式 可以使用通配符来匹配文件路径或文件 -perm [+-]访问模式 按照文件权限来查找文件 -regex 匹配模式 基于正则表达式来匹配文件路径 -readable -writable -executable -wholename PATTERN -size N[bcwkMG] 如:-size N[c] 查找文件长度为n块的文件,带有c时表示文件长度以字节计 -true -type [bcdpflsD] 查找某一类型的文件,诸如:b - 块设备文件。d - 目录。c - 字符设备文件。p - 管道文件。l - 符号链接文件。f - 普通文件。 -uid N -used N -user NAME 按照文件属主来查找文件 -xtype [bcdpfls] 注:N可以是 +N 或-N 或 N
动作项(action)
是对某一个文件进行某种动作,返回true或者false。
- -delete
- -print0
- -printf FORMAT
- -fprintf FILE FORMAT
- -fprint0 FILE
- -fprint FILE
- -ls -fls FILE
- -prune
- -quit
- -exec COMMAND ;
- -exec COMMAND {} + -ok COMMAND ;
- -execdir COMMAND ;
- -execdir COMMAND {} + -okdir COMMAND ;
实例
根据文件名查找
查找一个文件名是lilo.conf的文件,“/”表示搜索整个硬盘find / -name lilo.conf 快速查找文件比如smb.conf文件,从它的文件后缀“.conf”可以判断这是一个配置文件,那么它应该在/etc目录内find /etc -name smb.conf 根据部分文件名查找方法有时我们知道只某个文件包含有abvd这4个字,那么要查找系统中所有包含有这4个字符的文件find / -name '*abvd*'输入这个命令以后,Linux系统会将在/目录中查找所有的包含有abvd这4个字符的文件(其中*是通配符),比如abvdrmyz等符合条件的文件都能显示出来。使用混合查找方式查找文件在/etc目录中查找大于500000字节,并且在24小时内修改的某个文件,则可以使用-and (与)把两个查找参数链接起来组合成一个混合的查找方式find /etc -size +500000c -and -mtime +1 根据时间找出 3 天"以前"被改动过的文件 (前第三天以前 → 2011/09/05 12:00 以前的文件) (> 72 小时)find /var/log/ -mtime +3 -type f -print找出 3 天內被改动过的文件 (2011/09/05 12:00 ~ 2011/09/08 12:00 內的文件) (0 ~ 72 小时內)find /var/log/ -mtime -3 -type f -print找出前第 3 天被改动过的文件 (2011/09/04 12:00 ~ 2011/09/05 12:00 內的文件) (72 ~ 96 小时)find /var/log/ -mtime 3 -type f -print找出第 3 天被改动过的文件 (也可以这样写)find /var/log/ -mtime +2 -mtime -4 -type f -print根据文件名或正则表达式匹配搜索,使用name选项
文件名选项是find命令最常用的选项,要么单独使用该选项,要么和其他选项一起使用。可以使用某种文件名模式来匹配文件,记住要用引号将文件名模式引起来。
文件名 find ~ -name "*.log" -print
不管当前路径是什么,如果想要在自己的根目录$HOME中查找文件名符合*.log的文件,使用~作为 'pathname'参数,波浪号~代表了你的$HOME目录。find ~ -name "*" -print查找$HOME目录中的文件find . -name "*.log" -print要在当前目录及子目录中查找所有的‘ *.log‘文件find . -name "[A-Z]*" -print要的当前目录及子目录中查找文件名以一个大写字母开头的文件find /etc -name "host*" -print要在/etc目录中查找文件名以host开头的文件find / -name "*" -print要想让系统高负荷运行,就从根目录开始查找所有的文件find . -name "[a-z][4-9].log" -print如果想在当前目录查找文件名以一个小写字母开头,最后是4到9加上.log结束的文件find . -name "[a-z][a-z][0--9][0--9].txt" -print在当前目录查找文件名以两个小写字母开头,跟着是两个数字,最后是.txt的文件,此命令就能够返回名为ax37.txt的文件find /root/ -name "*.txt" -print匹配所有以.txt结尾的文件名find . /root/ \( -name "*.txt" -o -name "*.pdf" \) -print匹配多个条件,可以使用OR条件操作使用"!"否定参数 find . ! -name "*.txt"匹配所有不是以.txt结尾的文件名根据文件权限搜索,使用-perm选项
如果希望按照文件权限模式来查找文件的话,可以采用-perm选项。你可能需要找到所有用户都具有执行权限的文件,或是希望查看某个用户目录下的文件权限类型。在使用这一选项的时候,最好使用八进制的权限表示法。
在当前目录下查找文件权限位为755的文件,即文件属主可以读、写、执行,其他用户可以读、执行的文件[root@localhost test]#find . -perm 755 -print
. ./scf ./scf/lib ./scf/service ./scf/service/deploy ./scf/service/deploy/product ./scf/service/deploy/info ./scf/doc ./scf/bin [root@localhost test]#还有一种表达方法:在八进制数字前面要加一个横杠-,表示都匹配,如-007就相当于777,-006相当于666,-005相当于555。
-007是查找含其它用户(不同组,非属主)可读,写,执行的文件.并不一定要同组可读写,-是指最少权限为007[root@localhost test]# ll 总计 316 -rw-r--r-- 1 root root 302108 11-13 06:03 log2012.log -rw-r--r-- 1 root root 61 11-13 06:03 log2013.log -rw-r--r-- 1 root root 0 11-13 06:03 log2014.log -rw-r--r-- 1 root root 0 11-13 06:06 log2015.log drwxr-xr-x 6 root root 4096 10-27 01:58 scf drwxrwxr-x 2 root root 4096 11-13 06:08 test3 drwxrwxr-x 2 root root 4096 11-13 05:50 test4 [root@localhost test]#
find . -perm -005
. ./test4 ./scf ./scf/lib ./scf/service ./scf/service/deploy ./scf/service/deploy/product ./scf/service/deploy/info ./scf/doc ./scf/bin ./test3 [root@localhost test]#基于目录的深度搜索
使用-maxdepth和-mindepth参数来限制find命令遍历目录的深度。-maxdepth和-mindepth应当作为find的第三个参数出现,如果作为第四个或之后的参数,则会影响find的效率。
find . -maxdepth 1 -type f
列出当前目录下的所有普通文件find -maxdepth 2 -name passwd查找根目录和根目录的和只展开一级的子目录中查找find / -maxdepth 3 -name passwd在根目录和根目录下展开两级查找passwd文件find -mindepth 3 -maxdepth 5 -name passwd 在根目录的第二级和第四级之间查找根据路径搜索
-path模式
-path可以使用通配符来匹配文件路径或文件$find . -path "*include/apu*"
./httpd-2.2.22/srclib/apr-util/include/apu_version.h ./httpd-2.2.22/srclib/apr-util/include/apu.hw ./httpd-2.2.22/srclib/apr-util/include/apu_errno.h ./httpd-2.2.22/srclib/apr-util/include/apu.hnw -regex模式-regex是基于正则表达式来匹配文件路径。下面命令匹配.py或.sh文件$find . -regex ".*\(\.py\|\.ssh\)$"
./.ssh ./httpd-2.2.22/srclib/apr/build/gen-build.py使用-prune
如果在查找文件时希望忽略某个目录,因为你知道那个目录中没有你所要查找的文件,那么可以使用-prune选项来指出需要忽略的目录。在使用-prune选项时要当心,因为如果你同时使用了-depth选项,那么-prune选项就会被find命令忽略。
忽略某个目录
如果希望在test目录下查找文件,但不希望在test/test3目录下查找find test -path "test/test3" -prune -o -print在test 目录下查找不在test4子目录之内的所有文件find test -path "test/test4" -prune -o -print-path "test" -prune -o -print 是 -path "test" -a -prune -o -print 的简写表达式按顺序求值, -a 和 -o 都是短路求值,与 shell 的 && 和 || 类似。避开多个文件夹 find test \( -path test/test4 -o -path test/test3 \) -prune -o -print
如果 -path "test" 为真,则求值 -prune , -prune 返回真,与逻辑表达式为真;否则不求值 -prune,与逻辑表达式为假。
如果 -path "test" -a -prune 为假,则求值 -print ,-print返回真,或逻辑表达式为真;否则不求值 -print,或逻辑表达式为真。圆括号表示表达式的结合。 \ 表示引用,即指示 shell 不对后面的字符作特殊解释,而留给 find 命令去解释其意义。查找某一确定文件,-name等选项加在-o 之后 find test \(-path test/test4 -o -path test/test3 \) -prune -o -name "*.log" -print按文件属主查找文件,使用user和nouser选项
find ~ -user peida -print
在$HOME目录中查找文件属主为peida的文件find /etc -user peida -print在/etc目录下查找文件属主为peida的文件find /home -nouser -print为了查找属主帐户已经被删除的文件,可以使用-nouser选项。在/home目录下查找所有的这类文件文件所属于的用户组,使用group和nogroup选项
find /apps -group gem -print
在/apps目录下查找属于gem用户组的文件find / -nogroup-print找没有有效所属用户组的所有文件,可以使用nogroup选项按照更改时间或访问时间等查找文件
如果希望按照更改时间来查找文件,可以使用mtime,atime或ctime选项。
如果系统突然没有可用空间了,很有可能某一个文件的长度在此期间增长迅速,这时就可以用mtime选项来查找这样的文件。
用减号-来限定更改时间在距今n日以内的文件,而用加号+来限定更改时间在距今n日以前的文件。find / -mtime -5 -print
在系统根目录下查找更改时间在5日以内的文件find /var/adm -mtime +3 -print为了在/var/adm目录下查找更改时间在3日以前的文件查找比某个文件新或旧的文件,使用-newer选项
如果希望查找更改时间比某个文件新但比另一个文件旧的所有文件,可以使用-newer选项。它的一般形式为:newest_file_name ! oldest_file_name
查找更改时间比文件log2012.log新但比文件log2017.log旧的文件[root@localhost test]# ll 总计 316 -rw-r--r-- 1 root root 302108 11-13 06:03 log2012.log -rw-r--r-- 1 root root 61 11-13 06:03 log2013.log -rw-r--r-- 1 root root 0 11-13 06:03 log2014.log -rw-r--r-- 1 root root 0 11-13 06:06 log2015.log -rw-r--r-- 1 root root 0 11-16 14:41 log2016.log -rw-r--r-- 1 root root 0 11-16 14:43 log2017.log drwxr-xr-x 6 root root 4096 10-27 01:58 scf drwxrwxr-x 2 root root 4096 11-13 06:08 test3 drwxrwxr-x 2 root root 4096 11-13 05:50 test4 [root@localhost test]#find -newer log2012.log ! -newer log2017.log
. ./log2015.log ./log2017.log ./log2016.log ./test3 [root@localhost test]#查找更改时间在比log2012.log文件新的文件[root@localhost test]#find -newer log2012.log
. ./log2015.log ./log2017.log ./log2016.log ./test3 [root@localhost test]#使用type选项
find /etc -type d -print
在/etc目录下查找所有的目录find . ! -type d -print在当前目录下查找除目录以外的所有类型的文件find /etc -type l -print在/etc目录下查找所有的符号链接文件使用size选项
可以按照文件长度来查找文件,这里所指的文件长度既可以用块(block)来计量,也可以用字节来计量。以字节计量文件长度的表达形式为N c;以块计量文件长度只用数字表示即可。
在按照文件长度查找文件时,一般使用这种以字节表示的文件长度,在查看文件系统的大小,因为这时使用块来计量更容易转换。find . -size +1000000c -print
在当前目录下查找文件长度大于1 M字节的文件find /home/apache -size 100c -print在/home/apache目录下查找文件长度恰好为100字节的文件find . -size +10 -print在当前目录下查找长度超过10块的文件(一块等于512字节)使用depth选项
在使用find命令时,可能希望先匹配所有的文件,再在子目录中查找。使用depth选项就可以使find命令这样做。
这样做的一个原因就是,当在使用find命令向磁带上备份文件系统时,希望首先备份所有的文件,其次再备份子目录中的文件。find / -name "CON.FILE" -depth -print
从文件系统的根目录开始,查找一个名为CON.FILE的文件使用mount选项
在当前的文件系统中查找文件(不进入其他文件系统),可以使用find命令的mount选项。
find . -name "*.XC" -mount -print
从当前目录开始查找位于本文件系统中文件名以XC结尾的文件使用exec或ok来执行shell命令
当匹配到一些文件以后,可能希望对其进行某些操作,这时就可以使用-exec选项。-exec选项让find命令对匹配的文件执行该参数所给出的shell命令。相应命令的形式为:'COMMAND' {} \;
- 一旦find命令匹配到了相应的文件,就可以用-exec项中的命令对其进行操作。任何形式的命令都可以在-exec选项中使用。(在有些操作系统中只允许-exec选项执行诸如l s或ls -l这样的命令)。
- 大多数用户使用这一选项是为了查找旧文件并删除它们。这里我强烈地建议你在真正执行rm命令删除文件之前,最好先用ls命令看一下,确认它们是所要删除的文件。
- -ok和-exec的作用相同,只不过以一种更为安全的模式来执行该参数所给出的shell命令,在执行每一个命令之前,都会给出提示,让用户来确定是否执行。
'COMMAND' {} \;
'COMMAND',根据实际情况使用相应的shell命令。
“{}”是一对大括号,在它们之前有空格,它们之后也有空格,但两个大括号之间没有空格。
“\;”是转义“;”。因为“;”是shell的关键字,所以需要加“\”转义。之间不能有空格。find . -type f -exec ls -l {} \;
find命令匹配到了当前目录下的所有普通文件,并在-exec选项中使用ls -l命令将它们列出。find logs -type f -mtime +5 -exec rm {} \;
在/logs目录中查找更改时间在5日以前的文件并删除它们find /etc -name "password*" -exec grep "rounder" {} \;
find命令首先匹配所有文件名为“password*”的文件,例如password,password.old,password.bak,然后执行grep命令看看在这些文件中是否存在一个rounder用户查找并删除dir1目录下更改时间小于一天的文件,删除时提示是否删除? y删除 n不删除使用-okbixiaopeng@bixiaopengtekiMacBook-Pro testshell$find dir2 -name "*.txt" -mtime -1 -ok rm {} \;
"rm dir2/cpf1.txt"? y "rm dir2/cpf12.txt"? y "rm dir2/f1.txt"? y "rm dir2/f2.txt"? n使用-execbixiaopeng@bixiaopengtekiMacBook-Pro testshell$find dir2 -name "*.txt" -mtime -1 -exec rm -i {} \;
remove dir2/f2.txt? nfind和xargs
在使用find命令的-exec选项处理匹配到的文件时,find命令将所有匹配到的文件一起传递给exec执行。不幸的是,有些系统对能够传递给exec的命令长度有限制,这样在find命令运行几分钟之后,就会出现溢出错误。错误信息通常是“参数列太长”或“参数列溢出”。这就是xargs命令的用处所在,特别是与find命令一起使用。find命令把匹配到的文件传递给xargs命令,而xargs命令每次只获取一部分文件而不是全部,不像-exec选项那样。这样它可以先处理最先获取的一部分文件,然后是下一批,并如此继续下去。
在有些系统中,使用-exec选项会为处理每一个匹配到的文件而发起一个相应的进程,并非将匹配到的文件全部作为参数一次执行;这样在有些情况下就会出现进程过多,系统性能下降的问题,因而效率不高;而使用xargs命令则只有一个进程。另外,在使用xargs命令时,究竟是一次获取所有的参数,还是分批取得参数,以及每一次获取参数的数目都会根据该命令的选项及系统内核中相应的可调参数来确定。
查找系统中的每一个普通文件,然后使用xargs命令来测试它们分别属于哪类文件:下面的例子在整个系统中查找内存信息转储文件 (core dump),然后把结果保存到/tmp/core.log 文件中:$ find . -name "core" -print | xargs echo "" >/tmp/core.log下面的例子在/apps/audit目录下查找所有用户具有读、写和执行权限的文件,并收回相应的写权限:$ find /apps/audit -perm -7 -print | xargs chmod o-w在下面的例子中,我们用g r e p命令在所有的普通文件中搜索device这个词:$ find / -type f -print | xargs grep "device"在下面的例子中,我们用grep命令在当前目录下的所有普通文件中搜索DBO这个词:$ find . -name \* -type f -print | xargs grep "DBO"\用来取消find命令中的*在shell中的特殊含义删除3天以前的所有东西$ find ./ -mtime +3 -print|xargs rm -f –r