LinuxLinux学习之路

Linux命令学习手册-find

2019-12-24  本文已影响0人  QuietHeart

find pathname -options [-print -exec -ok ...]

功能

find 用于查找符合某些特性的文件。由于 find 具有强大的功能,所以它的选项也很多,其中大部分选项都值得我们花时间来了解一下。

即使系统中含有网络文件系统( NFS), find 命令在该文件系统中同样有效,只要你具有相应的权限。

描述

find 命令的参数

find 的所有参数均为可选

find 命令选项

另外,下面三个的区别:

使用 execok 来执行shell命令

使用 find 时,只要把想要的操作写在一个文件里,就可以用 exec 来配合 find 查找,很方便的。

在有些操作系统中只允许 -exec 选项执行诸如 lsls -l 这样的命令。大多数用户使用这一选项是为了查找旧文件并删除它们。建议在真正执行 rm 命令删除文件之前,最好先用 ls 命令看一下,确认它们是所要删除的文件。

exec 选项后面跟随着所要执行的命令或脚本,然后是一对儿 { } ,一个空格和一个 \ ,最后是一个分号。为了使用 exec 选项,必须要同时使用 print 选项。如果验证一下 find 命令,会发现该命令只输出从当前路径起的相对路径及文件名。

举例

按名称

在当前目录中查找任何扩展名为 .c 的文件:

$find ./ -name '*.c'

$find ./ -name \*.c

$find -name '*.c'

输入之后,输出如下:

./hello.c
./1/main.c
./1/hello.c
./hello2.c

这里,当前目录只用 . 也行,如果不用转义, *.c 必须括在引号(单/双)当中,如果不指定路径,将在当前目录找; 默认把子目录下的也都找出来了。

./test./viStudy 目录查找所有 .c 文件:

$find test viStudy/ -name '*.c'

输入之后,输出如下:

test/test_out_direct.c
viStudy/hello.c
viStudy/1/main.c
viStudy/1/hello.c
viStudy/hello2.c

这里,如果您没有相应的权限,您在开始浏览许多目录时将生成错误消息例如如下的提示:

find:  /tmp/orbit-root: Permission denied

可以不让错误输出,防止混乱:

$find /usr /home  /tmp -name "*.jar" 2>/dev/null

不区分大小写的 find 查找:

$find downloads -iname '*.gif'

输入之后,输出如下:

downloads/.xvpics/Calendar05_enlarged.gif
downloads/lcmgcfexsmall.GIF

这里,默认情况下, find 是区分大小写的。对于不区分大小写的 find ,将 -iname 测试替换为 -name

列出当前目录和所有子目录中的所有文件(包括隐藏文件)的完整清单:

$find

$find .

$find . -print

输入之后,输出如下:

.
./any
./tags
./hello.c
./1
./1/main.c
...省略...

按类型

查找某(当前)目录中的所有子目录:

$find . -type d

$find -type d

输入之后,输出如下:

.
./1

查找某(当前)目录中的所有符号链接:

$find . -type l

输入之后输出如下:

./hello2s

这里, ./hello2s 是一个软链接,这个命令显示的也是软链接。其他 find 可以找到的文件类型包括:

ls 列出软链接需要用 -ls ,用管道不行。如下:

$find . type l -ls

输出:

56231215    0 lrwxrwxrwx   1 quietheart member          6 May 16 16:14 ./hello2s -> hello2

从当前目录开始查找位于本文件系统中文件名以XC结尾的文件:

$ find . -name "*.XC" -mount -print

这里,在当前的文件系统中查找文件(不进入其他文件系统),使用了 find 命令的 mount 选项。

告知 find 在指定文件系统(例如 vfat )中查找:

$find / -name  "*.txt" -fstype vfat

还有

$find / -name  "*.txt" -mount 2

等等,不常用就不多说了。

按时间

查找在最近 1 *24小时内修改的所有文件:

$find . -mtime -1

输入之后输出如下:

./plsql/FORALLSample
./plsql/RegExpDNASample
/plsql/RegExpSample

查找恰好在 1 *24小时以前修改的所有文件:

$find . -mtime 1

查找 1 *24个多小时以前修改的所有文件:

$find . -mtime +1

这里, find 根据系统的时间戳搜索文件的选项。这些时间戳包括:

这里, ctime 则需要更多的解释。由于 inode 维护着每个文件上的元数据,因此,如果与文件有关的元数据发生变化,则 inode 数据也将变化。这可能是由一系列操作引起的,包括创建到文件的符号链接、更改文件权限或移动了文件等。由于在这些情况下,文件内容不会被读取或修改,因此 mtimeatime 不会改变,但 ctime 将发生变化。

这些时间选项都需要与一个值 n 结合使用,指定为 -nn+n:

查找在不到 1 分钟以前读取的所有文件:

$find . -amin -1

输入之后,输出如下:

./.bashrc
/.bash_history
./.xauthj5FCx1

这里是刚刚登陆系统就运行了这个命令,所以输出这样。默认情况下, -mtime-atime-ctime 指的是最近 24 小时。但是,如果它们前面加上了开始时间选项,则 24 小时的周期将从当日的开始时间算起。您还可以使用 mminamincmin 查找在不到 1 小时的时间内变化了的时间戳。

另外,应该注意的是,使用 find 命令查找文件本身将更改该文件的访问时间作为其元数据的一部分。

查找在当前目录中 hello2.c 文件之后被编辑过的所有文件:

$find . -newer hello2.c

输入之后输出如下:

.
./hello2s
./hello2h
./hello2

这里,需要注意硬链接的特殊性(我不说,只有你明白了才知道我说的意思)。使用 -newer-anewer-cnewer 选项与特定的文件比较查找已修改或访问过的文件。这类似于 -mtime-atime-ctime

查找更改时间比文件httpd1.conf新但比文件temp旧的文件:

$find -newer httpd1.conf  ! -newer temp -ls

其中, 是逻辑非符号。

按大小

查找所有大于 5MB 的用户文件:

$find / -size  +5000000c 2> /dev/null

输入之后,输出如下:

/var/log/lastlog
/var/log/cups/access_log.4
/var/spool/mail/bluher

这里,把错误的信息定位到 /dev/null 了。

结尾的 c 以字节为单位报告我们的结果。默认情况下, find 以 512 字节块的数量报告大小。如果我们将 c 替换为 k ,我们还会看到以千字节的数量报告的结果,如果使用 w ,则会看到以两字节字的数量报告的结果。

在当前目录下查找长度超过10块的文件(一块等于512字节):

$ find . -size +10 -print

搜索所有零字节文件并将它们移至 /tmp/zerobyte 文件夹:

$find test -type f  -size 0 -exec mv {} /tmp/zerobyte \;

这里, -exec 操作允许 find 在它遇到的文件上执行任何 shell 命令。在本文的后面部分,您将看到其用法的更多示例。大括号允许移动每个空文件。

查找test目录下的空文件:

$find test -empty

输入之后输出如下:

test/foo
test/test

查找空文件用的是 -empty 选项。

按权限、所属

在当前目录下查找文件权限位为 755 的文件:

$find . -perm 755 -print

还有一种表达方法:在八进制数字前面要加一个横杠 - ,表示都匹配,如 -007 就相当于 777-006 相当于 666 .

查找属于 user1name 或着属于 user2name 的文件:

$find / -user user1name -or -user user2name

查找既属于 user1name 又属于 user2name 用户的文件:

$find / -user user1name -and -user2name

查找在系统中属于非用户( ? )的文件:

$find /-nouser

查找在系统中属于 username 的文件:

$find / -user username

查找在系统中属于 groupname 的文件:

$find / -group groupname

按指定目录

希望在 /apps 目录下查找文件,但不希望在 /apps/bin 目录下查找:

$find /apps -path "/apps/bin" -prune -o -print

在使用 -prune 选项时要当心,因为如果你同时使用了 -depth 选项,那么 -prune 选项就会被 find 命令忽略。

/usr/sam 目录下查找不在 dir1 子目录之内的所有文件:

$find /usr/sam -path "/usr/sam/dir1" -prune -o -print

这里, find [-path ..] [expression] 在路径列表的后面的是表达式。

-path "/usr/sam" -prune -o -print-path "/usr/sam" -a -prune -o -print 的简写表达式按顺序求值, -a-o 都是短路求值,与 shell 的 &&|| 类似。

如果 -path "/usr/sam"= 为真,则求值 =-prune , -prune 返回真,与逻辑表达式为真;否则不求值 -prune ,与逻辑表达式为假。

如果 -path "/usr/sam" -a -prune 为假,则求值 -print-print 返回真,或逻辑表达式为真;否则不求值 -print ,或逻辑表达式为真。

这个表达式组合特例可以用伪码写为

if -path "/usr/sam"  then
          -prune
else
          -print

避开多个文件夹:

$find /usr/sam \( -path /usr/sam/dir1 -o -path /usr/sam/file1 \) -prune -o -print

这里,圆括号表示表达式的结合。 \ 表示引用,即指示 shell 不对后面的字符作特殊解释,而留给 find 命令去解释其意义。

确保先在一个目录中进行查找,然后才在其子目录中进行查找:

$find -name "*test*" -depth

输入之后,输出:

./test/test
./test
./localbin/test
./localbin/test_shell_var
./localbin/test.txt
./test2/test/test
./test2/test
./test2

find 在至少下至目录树三个级别的目录中查找:

$find / -mindepth 3  -name "*log"

在目录树的前三个级别中查找日志文件:

$find / -maxdepth 3  -name "*log"

查找并执行命令:

用 =ls -l=命令列出所匹配到的文件:

$find . -type f -exec ls -l {  } \;

输入之后,输出:

-rw-r--r--    1 root     root        34928 2003-02-25  ./conf/httpd.conf
-rw-r--r--    1 root     root        12959 2003-02-25  ./conf/magic
-rw-r--r--    1 root     root          180 2003-02-25  ./conf.d/README

这里, exec 选项后面跟随着所要执行的命令或脚本,然后是一对儿 {} ,一个空格和一个 \ ,最后是一个分号,注意 {} 内可以没有空格,但是 {} 后面、 \ 前面要有一个空格。

/logs 目录中查找更改时间在5日以前的文件并删除它们:

$find logs -type f -mtime +5 -exec rm {  } \;

在shell中用任何方式删除文件之前,应当先查看相应的文件,一定要小心!当使用诸如 mvrm 命令时,可以使用 -exec 选项的安全模式。

当前目录中查找所有文件名以 .LOG 结尾、更改时间在5日以上的文件并删除,删除之前先给提示:

$find . -name "*.conf"  -mtime +5 -ok rm {  } \;

输入之后,输出如下提示:

< rm ... ./conf/httpd.conf > ? n

这里,按 y 键删除文件,按 n 键不删除。

匹配所有文件名为 passwd* 的文件,然后执行 grep 命令看这些文件中是否存在 sam 用户:

$find /etc -name "passwd*" -exec grep "sam" {  } \;

输入之后,输出:

sam:x:501:501::/usr/sam:/bin/bash

当前目录中文件属主具有读、写权限,并且文件所属组的用户和其他用户具有读权限的文件:

$find . -type f -perm 644 -exec ls -l {  } \;

查找 /var/logs 目录中更改时间在7日以前的普通文件,并在删除之前询问它们:

$find /var/logs -type f -mtime +7 -ok rm {  } \;

查找系统中所有属于 root 组的文件:

$find . -group root -exec ls -l {  } \;

输入之后,输出:

-rw-r--r--    1 root     root          595 10月 31 01:09 ./fie1

这里实际不用 -exec 也行,即: $find . -group root 。不过为了更详细列出相关的信息,使用 exec 选项对每个文件执行了 ls

查找并删除访问时间在7日以来、含有数字后缀的 admin.log 文件:

$find . -name "admin.log[0-9][0-9][0-9]" -atime -7  -ok rm {  } \;

输入之后,输出:

< rm ... ./admin.log001 > ? n
< rm ... ./admin.log002 > ? n
< rm ... ./admin.log042 > ? n
< rm ... ./admin.log942 > ? n

这里,只寻找了3位数的数字。

高效的查找执行:

使用 find 命令的 -exec 选项处理匹配到的文件时, find 命令将所有匹配到的文件一起传递给 exec 执行。但有些系统对能够传递给 exec 的命令长度有限制,这样在 find 命令运行几分钟之后,就会出现溢出错误;还可能导致有些系统进程过多,系统性能下降的问题,因而效率不高.

使用 xargs 命令则只有一个进程。另外,在使用 xargs 命令时,究竟是一次获取所有的参数,还是分批取得参数,以及每一次获取参数的数目都会根据该命令的选项及系统内核中相应的可调参数来确定。

下面是 xargs 命令同 find 命令一起使用的一些例子:

查找系统中的每一个普通文件,然后使用xargs命令来测试它们分别属于哪类文件:

$find . -type f -print | xargs file

输入之后,输出:

./.kde/Autostart/Autorun.desktop: UTF-8 Unicode English text
./.kde/Autostart/.directory:      ISO-8859 text\
...省略...

当前目录下查找 file 开头的文件然后把结果保存到 /tmp/core.log 文件中:

$find . -name "file*" -print | xargs echo "" > /temp/core.log

在当前目录下查找所有用户具有读、写和执行权限的文件,并收回相应的写权限:

$find . -perm -7 -print | xargs chmod o-w

grep 命令在当前目录下的所有的普通文件中搜索 hostname 这个词:

$find . -type f -print | xargs grep "hostname"

$find . -name \* -type f -print | xargs grep "hostname"

输入之后,输出:

./httpd1.conf:#     different IP addresses or hostnames and have them handled by the
./httpd1.conf:# VirtualHost: If you want to maintain multiple domains/hostnames on your

注意,这里, \ 用来取消 find 命令中的 * 在shell中的特殊含义。

其它

上一篇下一篇

猜你喜欢

热点阅读