美文网首页
Linux find基础

Linux find基础

作者: shenzhenboy | 来源:发表于2017-02-28 16:09 被阅读160次

    搜索文件在使用操作系统中是非常频繁的操作,一个系统中可能有成千上万的文件,怎么快速找到想要的文件是提升效率的关键。Linux中我们可以使用强大的find命令。find命令可以说是Linux中最常用也最复杂的命令,特别是和其他命令一起执行的时候。由于find具有强大的功能,所以它的选项也非常多,其中大部分都值得我们花时间了解一下。

    find命令的一般形式

    find [-H | -L | -P] [-EXdsx] [-f path] path ... [expression]
    find [-H | -L | -P] [-EXdsx] -f path [path ...] [expression]
    

    上面的find命令可以简化为:

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

    命令参数:

    pathname: find命令所要查找的目录路径。例如用 . 表示当前目录,用 / 表示根目录
    
    -print: 将find命令匹配到的文件输出到标准输出
    -exec: 将find命令匹配到的文件执行该参数指定的shell命令。相应的命令形式为 'command' {};
    -ok: 和 -exec 相同,只不过更安全
    

    find命令最简单的使用是,搜索一个或多个目录。

    $ find .
    .
    ./.android
    ./.android/adbkey
    ./.android/adbkey.pub
    ./.android/androidwin.cfg
    ./.android/avd
    ./.android/cache
    ./.android/cache/api-versions-6.bin
    [...]
    $
    $ find / 
    /
    find: /.fseventsd: Permission denied
    /.MobileBackups
    find: /.MobileBackups: Permission denied
    /.OSInstallerMessages
    /.PKInstallSandboxManager
    /.PKInstallSandboxManager-SystemSoftware
    /.vol
    /Applications
    /Applications/.DS_Store
    /Applications/.localized
    /Applications/Adobe Application Manager
    /Applications/Adobe Photoshop CC 2014
    /Applications/Adobe Photoshop CC 2014/Adobe Photoshop CC 2014.app
    [...]
    $
    

    也可以一次搜索多个目录:

    $ find . /
    [...] // 输出结果太多,省略
    

    如果仅仅只是列出某个目录的所有文件就感受不到find的强大。find可以通过组合各种选项来组成搜索条件来完成搜索,而且还可以运用各种相关的操作。

    测试条件

    我们可以根据文件类型来搜索。find支持的文件类型如下(-type 参数):

    文件类型 描述
    b 块设备文件
    c 字符设备文件
    d 目录
    f 普通文件
    l 符号链接

    比如我们只想搜索某个目录下面所有的子目录:

    $ find . -type d 
    .
    ./.android
    ./.android/avd
    ./.android/cache
    ./.atom
    ./.atom/.apm
    ./.atom/.apm/_locks
    ./.atom/.apm/atom-autocomplete-php
    ./.atom/.apm/atom-autocomplete-php/0.18.9
    ./.atom/.apm/atom-autocomplete-php/0.18.9/package
    [...]
    $
    

    我们也可以只搜索某个目录下的普通文件:

    $ find ~ -type f | wc -l
    868386
    $
    

    也可以根据文件大小来搜索(-size 参数):

    字符 单位
    b 512个字节块。如果没有指定单位,则这是默认值。
    c 字节
    w 两个字节的字
    k 千字节(1024字节)
    M 兆字节(1048576字节)
    G 千兆字节(1073741824字节)

    我们可以搜索目录下面文件大小大于1G的文件:

    $ find ~ -type f -size +1G
    /Documents/Virtual Machines.localized/Windows 10 x64 2.vmwarevm/Virtual Disk-s001.vmdk
    ./Documents/Virtual Machines.localized/Windows 10 x64 2.vmwarevm/Virtual Disk-s002.vmdk
    ./Documents/Virtual Machines.localized/Windows 10 x64 2.vmwarevm/Virtual Disk-s003.vmdk
    [...]
    $
    

    上面的例子使用了文件类型和文件大小一起作为搜索的测试条件,只有文件类型是普通文件而且大小大于1G的文件才会被搜索到。我们也可以再增加搜索条件:

    $ find ~ -type f -name "*.png" -size +1M | wc -l
    5543
    $
    

    上面的例子中我们使用了-name测试条件,后面跟通配符模式。注意我们使用双引号括起来,是为了阻止bash展开星号。上面的测试条件是找到文件名以png结尾,并且是普通文件类型的文件,而且文件大小要大于1M。如果在数字参数前面加上+或者-则表示大于或者小于指定数。

    find的其他测试条件,下面是一些常见的测试条件,在数值参数的前面可以使用+或者-

    测试条件 描述
    -cmin n 匹配的文件和目录的内容或属性最后修改时间正好在 n 分钟之前。 指定少于 n 分钟之前,使用 -n,指定多于 n 分钟之前,使用 +n。
    -cnewer file 匹配的文件和目录的内容或属性最后修改时间早于那些文件。
    -ctime n 匹配的文件和目录的内容和属性最后修改时间在 n*24小时之前。
    -empty 匹配空文件和目录。
    -group name 匹配的文件和目录属于一个组。组可以用组名或组 ID 来表示。
    -iname pattern 就像-name 测试条件,但是不区分大小写。
    -inum n 匹配的文件的 inode 号是 n。这对于找到某个特殊 inode 的所有硬链接很有帮助。
    -mmin n 匹配的文件或目录的内容被修改于 n 分钟之前。
    -mtime n 匹配的文件或目录的内容被修改于 n*24小时之前。
    -name pattern 用指定的通配符模式匹配的文件和目录。
    -newer file 匹配的文件和目录的内容早于指定的文件。当编写 shell 脚本,做文件备份时,非常有帮助。 每次你制作一个备份,更新文件(比如说日志),然后使用 find 命令来决定自从上次更新,哪一个文件已经更改了。
    -nouser 匹配的文件和目录不属于一个有效用户。这可以用来查找 属于删除帐户的文件或监测攻击行为。
    -nogroup 匹配的文件和目录不属于一个有效的组。
    -perm mode 匹配的文件和目录的权限已经设置为指定的 mode。mode 可以用 八进制或符号表示法。
    -samefile name 相似于-inum 测试条件。匹配和文件 name 享有同样 inode 号的文件。
    -size n 匹配的文件大小为 n。
    -type c 匹配的文件类型是 c。
    -user name 匹配的文件或目录属于某个用户。这个用户可以通过用户名或用户 ID 来表示。

    操作符

    上面的测试条件只是一部分,限于篇幅只能列出笔记常用的。那么这么多测试条件如果都并列写在一起将不便于阅读。所以find提供了逻辑操作符来创建复杂的测试条件,也便于阅读和维护。逻辑操作符如下:

    操作符 描述
    -and 如果操作符两边的测试条件都是真,则匹配。可以简写为 -a。 注意若没有使用操作符,则默认使用 -and。
    -or 若操作符两边的任一个测试条件为真,则匹配。可以简写为 -o。
    -not 若操作符后面的测试条件是真,则匹配。可以简写为一个感叹号(!)。
    () 把测试条件和操作符组合起来形成更大的表达式。这用来控制逻辑计算的优先级。

    注意,find命令从左往右计算,而且要注意圆括号在bash中要转义

    我们可以使用上面的逻辑操作符来构造复杂的测试条件,例如只查找特定某些文件:

    find . \(-name "*.pdf" -or -name "*.txt"\)

    上面的例子会打印当前目录下以.txt.pdf结尾的文件名。也可以找出目录下不是pdf的普通文件:

    find . ! -name "*.pdf"

    逻辑操作符可以描述为下面的简短形式。逻辑操作符还有一种和其他编程语言相同的特性:短路。下面是逻辑操作符的执行情况:

    expr1 -operator expr2

    expr1的结果 操作符 expr2的执行情况
    -and 总要执行
    -and 从不执行
    -or 从不执行
    -or 总要执行

    预定义操作

    find除了可以根据特定条件搜索文件外,还可以在搜索到文件之后根据搜索结果执行预定义的操作。find预定义的常用的操作如下表:

    操作 描述
    -print 把匹配文件的全路径名输送到标准输出。如果没有指定其它操作,这是 默认操作。
    -delete 删除匹配到的文件
    -ls 对匹配到的结果执行 ls -dils 命令,然后将结果输出到 STDOUT
    -quit 一旦找到一个匹配,就退出

    find .

    会输出当前目录的所有文件和子目录,这相对于:

    find . -print

    也可以使用-delete来删除搜索到的文件和目录:

    find . -empty -delete
    find . -type f -name '*.txt' -delete

    上面的第一条命令会删除当前目录下的空目录和空文件,第二条命令会删除当前目录下面所有的txt文件。( 好像例子不是太好:( )
    当使用-delete时得特别小心,可以先用print输出看看里面有没有不能删除的文件

    自定义操作

    find除了可以使用预定义的操作之外,还可以通过-exec来自定义操作:

    find path [expression] -exec command {} ;

    上面的-exec是表示自定义操作的开始,command就是shell命令的名字,{}是当前路径名的符号表示,分号是命令结束的标志。

    find . -type f -name "*.zip" -size +100M -exec rm {} \;

    删除当前目录下大于100M的压缩文件。上面命令中的{}代表find找到的文件路径,find的结果会放到{}位置之中作为rm的参数。

    find . -type f -name ".pdf" -exec ls -l {} \;

    上面的命令用于输出当前目录下所有的pdf文件详情。当使用-exec时,每找到一个匹配就会执行一次-exec后面的命令。有时候我们可能希望将find的结果作为一个整体然后再运行额外的命令,这个时候就可以使用外部命令xargsxargs从标准输入接受输入,并把输入转换为一个特定命令的参数列表,这样命令就不用每匹配到一个文件或目录就执行一次。

    find ~ type f -name "*.pdf" | xargs ls -l

    因为xargs接受标准输入,所以把find的结果用管道(pipe)到xargs的输入,xargs会把输入构造为ls的参数列表,然后执行ls命令。这种方式比-exec方式快很多,ls执行的次数远远小于-exec的匹配到文件就执行一次命令。
    xargs后面的命令并不是只执行一次,这取决于输入的参数的个数,如果超过了bash能够处理的最大长度,xargs会使用最大的参数长度执行后面的命令,然后重复这个过程,直到所有的输入都执行完。

    相关文章

      网友评论

          本文标题:Linux find基础

          本文链接:https://www.haomeiwen.com/subject/bxgxgttx.html