谢晓波 bio photo

谢晓波

I am a master student from Beijing Normal University. Interested in machine learning and applications

Email Google+ Github Weibo

Find命令是linux用非常常用的命令,功能也非常强大。平时仅仅是用了下Find的几个简单的用法,并没有深入去研究高级用法。借着看leveldb的makefile的契机又研究下下Find的有关命令。特此记录一下。

一般格式

Find命令的一般格式为如下:

$ find path -option [-print] [ -exec -ok ] {} \;
  • path: find命令查找路径
  • -option: find命令选项,常见的有-name, -type, -prune等,主要用于过滤。稍后详细解释。
  • -print: find命令将匹配的文件输出到标准输出
  • -exec: find命令对匹配的文件执行该参数给出的shell命令。稍后详细解释。
  • -ok: 和exec类似,不同的是每次执行参数给出的shell命令时会给出提示,让用户确定是否执行。

常见选项和用法

这节主要结合实际例子解释find命令的常见的-option有哪些,如何理解和使用,以及-print, -exec, -ok等的用法。

  • -name

    按文件名查找文件。最常用的Find选项。比如说我想找出当前目录下所有的.h文件,命令如下:

     $ find ./ -name "*.h"
    
  • -type

    按类型查找文件。可选type有:

    • b 块设备文件
    • d 目录
    • c 字符设备文件
    • p 管道文件
    • l 符号链接文件
    • f 普通文件

    例如:我们想查找/usr/bin下的所有链接文件,命令如下:

      $ find /usr/bin -type l 
    
  • -size n

    按照文件大小查找。其中n为块的数量,每个块为512Byte。n后面可以紧接大小单位。可选的单位有:

    • k kilobytes (1024 bytes)
    • M megabytes (1024 kilobytes)
    • G gigabytes (1024 megabytes)
    • T terabytes (1024 gigabytes)
    • P petabytes (1024 terabytes)

    例如,我们想找出download文件下所有大于1G的文件:

      $ find ~/Download/ -size +1G
    

    或者我们想找出当前目录下所有大小为0的空文件,并删除,命令为:

      $ find ./ -size 0 -exec rm -rf {} \;
    
  • -prune

    -prune的含义是剪枝,对find匹配到的文件目录不再进入子目录查找。-prune的含义经常被误解为对匹配的进行过滤。-prune引起误解最主要的原因是因为类似这样的用法,比如我想找出当前文件夹下包含”test”之外的所有文件:

      $ find ./ -name "*test*" -prune -o -print
    

    注意,这个的-prune仅仅是剪枝,对匹配到”test”的文件或者目录不进入其子目录。真正过滤作用的是这里的-o,即or逻辑运算符。这里应该这么理解,当匹配到“test”的文件或者目录时,or的前半部分为真,所以不执行后半部分,即不打印匹配到的文件或目录。否则,打印出来。这样就相当于过滤掉含“test”的文件或目录。下面再举一个例子说明-prune的真正含义

    prune_example

  • -atime
  • -mtime
  • -ctime

    这三个都是按照时间来查找。atime表示文件读取或访问的时间。mtime表示文件内容上次修改的时间。ctime表示文件状态变化的时间。和文件元数据有关的变化都会导致ctime时间的变化,比如创建到文件的链接符号,更改文件权限,移动文件等等。ctime都会发生变化。

    这些时间选项都需要与一个值n来结合使用,指定为+n,-n或者n。+n表示大于这个时间段,-n表示小于,n表示刚好等于。n后面可以接时间单位,可以指定为:

    • s second
    • m minute (60 seconds)
    • h hour (60 minutes)
    • d day (24 hours)
    • w week (7 days)

    例如,我想找出当前文件夹下被修改超过一天的.cc文件,可以写成:

      $ find ./ -name "*.cc" -mtime +1d -print
    

    或者我们想找出超过一个月没用任何改动的大于2G的大文件,并执行删除:

      $ find ./ -size +2G -ctime +30d -exec rm {} \;
    

    又或者我们想找出10分钟内被修改所有文件,但不包含以”.doc”结尾的所有文件:

     $ find ./ -mtime -10m ! -name "*.doc"
    

与xargs结合

我们可以通过管道和xargs命令一起使用find。虽然功能和-exec类似,但是-exec命令有长度限制。如果Find出来的文件太多,使用-exec可能出现溢出错误。而xargs则是一次获取一部分文件执行。

我们给出一些常用的例子。比如用grep命令在所有”*.cc”文件中搜索“include”这个词。这个命令很有用,比如我经常需要在所有源代码里找出哪些文件出现了某个变量。

    $ find . -type f -name "*.cc" -print | xargs grep -rn "include"

再比如,我想找出当前文件中所有.git结尾的文件并删除

    $ find . -name .git | xargs rm -rf

这个命令我也常用。比方说,有个git托管的工程,我想删除这个文件夹。直接删除会弹出一堆询问是否删除.git文件的,一个个的确认让人崩溃。这时直接用这条命令可以删除git相关的管理文件。