find 命令详解

find 命令是linux 世界中查找文件用的最多的一个命令

最简单的用法如下

find dir -d(depth) 1 -type f(f 文件 d 文件夹) -ctime -1d

-atime 最后的访问时间
s       second
             m       minute (60 seconds)
             h       hour (60 minutes)
             d       day (24 hours)
             w       week (7 days)

             Any number of units may be combined in one -atime argument, for
             example, ``-atime -1h30m''.  Units are probably only useful when
             used in conjunction with the + or - modifier.
atime  access time
mtime modify time
ctime create time

比如 -mtime +1 就是1天以上的 -1 一天以内的 1 1天或者一天以上的

不带单位 默认是d 【天】

可以使用 stat 查看具体的一个文件的详细信息

现在我们详细了解一下find 命令常用的参数

参数名称是什么说明
-name 名字 可以是正则表达式 比如 -name '[a-z0-9]*.txt' 查找 名字的正则表达式
-perm 权限 -perm 664 查找664的文件 ;还有一种表达方法:在八进制数字前面要加一个横杠-,表示至少包含这个权限; 查找权限为644的文件或目录(需完全符合) find ./ -perm 664 查找用户/组权限为读写,其他用户权限为读(其他权限不限)的文件或目录 find ./ -perm -664
-depth 文件夹查找的深度
-prune 去掉某一个目录 不进行查找;在使用-prune选项时要当心,因为如果你同时使用了-depth选项,那么-prune选项就会被find命令忽略。如果希望在test目录下查找文件,但不希望在test/test3目录下查找,可以用 find test -path "test/test3" -prune -o -print 这边 -path 是绝对路径 所以-path 最好是 "*test/test3" 这样的
-type d 文件夹 f file l for link
-exec 对查找之后的内容进行 另外的操作 -exec ls {} ; 注意这个转义的 ;
-ok 加个一个确认 会在打印的时候确认 和 -exec 替换使用 只不过需要确认 比如上面的 -exec ls {} ; 变成了 -ok ls {} ;
-print 会打印查找的文件名字 全名 比如 find ~/Downloads/ -name "专供*" -print -exec cat {} ;· 会cat 文件的同时打印文件名称 如果没有 -print 的话没有 打印文件名称
-regex 通过正则表达式查找 文件的名称 find ~/Downloads/ -regex .专供. -print -exec cat {} ; 查找的是全名 !!! 【这个比较烦 】 所有一定要注意 .*专供.* 前后的.* 可以查找特定文件夹 里面的特定的文件
-name 根据名称查找文件 和正则表达式里面的* 不一样 * 这里匹配任意多个字符
-exec ls {} + 这个加号的意思是将所有输出等到 最后一次性让 ls 执行
-atime 【 access time】 find ./ -mtime -2d #查找两天内的文件 find ./ -mtime +2d #两天以上的 find ./ -mtime 2d #两天以上的以及两天以上的 注意的是哪怕ls 一下文件也会修改文件的access time 通过stat 查看
-mtime 【modified time 】 同上
-ctime 【changed time】 同上
-newer 查找文件更新时间比文件abc的内容更新时间新的文件 find ./ -newer abc
-anewer 查找文件访问时间比文件abc的内容更新时间新的文件 find ./ -anewer abc
-empty 查找空文件 或者 空目录
-delete 删除操作 比较危险
-user user 用户
-group group 筛选
-nouser 没用户的
-nogroup 没有group 的文件
find ./ -executable ! -readable 查找有执行权限但没有可读权限的文件 这个完全可以在权限里面设置 这个readable 和 executable 只有在 centos linux 里面有 unix 木有
-size 查找文件大小
-prune 不包含文件夹 或者文件
-path <pattern> 根据路径查找文件 复合pattern

-perm 权限 的例子

查找权限为644的文件或目录(需完全符合)

find ./ -perm 664

查找权限不是 644 的文件或者目录

find ./ ! -perm 644 # ! 表示取反

查找用户/组权限为读写,其他用户权限为读(其他权限不限)的文件或目录

find ./ -perm -664

-664 包含的含义是“至少包含 644”

下面的含义是 other 包含 read

find ./ -perm -o=r 或者 find ./ -perm -o=rw # 里面的的选项有 -o -u -g 权限有 rwx

在centos 等linux 中还支持 find / -maxdepth 2 -perm /u=s 这样的的语法


-size 例子

查找文件size小于10个字节的文件或目录 find ./ -size -10c

查找文件size等于10个字节的文件或目录 find ./ -size 10c

查找文件size大于10个字节的文件或目录 find ./ -size +10c

查找文件size小于10k的文件或目录 find ./ -size -10k

查找文件size小于10M的文件或目录 find ./ -size -10M

查找文件size小于10G的文件或目录 find ./ -size -10G

-prune 的例子

参考 https://stackoverflow.com/questions/1489277/how-to-use-prune-option-of-find-in-sh

[-prune man 里面这样说 永远返回真,它让find 忽略满足条件的 目录,假如 -d 指定的话 这个参数无用]

The thing I'd found confusing about about -prune is that it's an action (like -print), not a test (like -name). It alters the "to-do" list, but always returns true. 【-prune更像是一个语句,就像-print 一样 】

The general pattern 【语法】for using -prune is this:

find [path] [conditions to prune] -prune -o [your usual conditions] [actions to perform]

You pretty much always want the the -o immediately after -prune, because that first part of the test (up to including -prune) will return false for the stuff you actually want (ie: the stuff you don't want to prune out). 所有 -prune 后面要紧跟 -o [-o -a 还有 ! 或 与 非] -o 后面的内容才是你 想要的

Here's an example:

find . -name .snapshot -prune -o -name '*.foo' -print

This will find the ".foo" files that aren't under ".snapshot" directories. In this example, -name .snapshot is the "tests for stuff you want to prune", and -name '.foo' -print is the "stuff you'd normally put after the path".

上面有一点错误 -name .snapshot 不仅是对文件夹的筛选,对文件一样的筛选【作者提示 一定要在-o 语句 最后加上 -print 否则也不会有效】

Important notes:

If all you want to do is print the results you might be used to leaving out the -print action. You generally don't want to do that when using -prune.

The default behavior of find is to "and" the entire expression with the -print action if there are no actions other than -prune (ironically) at the end. That means that writing this:

find . -name .snapshot -prune -o -name '*.foo' # DON'T DO THIS is equivalent to writing this:

find . ( -name .snapshot -prune -o -name '*.foo' ) -print # DON'T DO THIS

which means that it'll also print out the name of the directory you're pruning, which usually isn't what you want.

上面的意思是如果没有最后的print find 命令会将后面的所有条件综合起来 然后在最后加一个 -print 那样的话 -o 【or】 就失去了我们想要的结果

Instead it's better to explicitly specify the -print action if that's what you want: find . -name .snapshot -prune -o -name '*.foo' -print # DO THIS

If your "usual condition" happens to match files that also match your prune condition, those files will not be included in the output. The way to fix this is to add a -type d predicate to your prune condition.

下面是作者展示的一个例子 在本文件夹中既有一个文件叫 .gitignore 又有一个文件夹叫 .git 左右想剔除所有含有.git字样的文件夹但是想查看包含.git字样的文件

find ./ -type d -name ".git*" -prune -o -type f -print

For example, suppose we wanted to prune out any directory that started with .git (this is admittedly somewhat contrived -- normally you only need to remove thing named exactly .git), but other than that wanted to see all files, including files like .gitignore. You might try this:

find . -name '.git*' -prune -o -type f -print # DON'T DO THIS This would not include .gitignore in the output. Here's the fixed version: find . -type d -name '.git*' -prune -o -type f -print # DO THIS Extra tip: if you're using the GNU version of find, the texinfo page for find has a more detailed explanation than its manpage (as is true for most GNU utilities).

参考 http://www.cnblogs.com/peida/archive/2012/11/16/2773289.html

上面的文章有个例子讲到

-a 和 -o 都是短路求值,与 shell 的 && 和 || 类似如果

查看下面的例子

例子1

find . -path "*testone" -prune -a -exec ls -al {} ;

上面的例子 查找path 包含 testone 的文件 并把它打印出来 这个例子有点多此一举

相当于

find . -path "*testone" -exec ls -al {}  ;

测试下来效果一样

例子2【摘抄】

避开多个文件夹: 命令: find test ( -path test/test4 -o -path test/test3 ) -prune -o -print

上面的例子很多人会测试失败原因是 -path 接受的是一个<pattern> 最好使用 *test4 代替 test/test4

我本地测试 避开 .git 和testone 文件夹

find . -type d -a ( -name ".git" -o -name "testone" ) -prune -o -print

一定要记得 -o !!!!

-depth 命令例子

参数-depth 的意思是:在处理目录以前首先处理目录下的子内容。 也即是说在不加-depth的时候, 处理顺序是首先处理目录本身,然后处理目录下的子内容。加不加-depth参数,会影响输出结构的输出顺序。

-mindepth 最少深度

dingmac@php_test$ find ./ -name 'test*' -depth -print
.//test.php
.//test1.php
.//test_2.php
.//test_global.php
.//testone/test1.txt
.//testone/test2.txt
.//testone
dingmac@php_test$ find ./ -name 'test*'  -print
.//test.php
.//test1.php
.//test_2.php
.//test_global.php
.//testone
.//testone/test1.txt
.//testone/test2.txt

-d n 如果-d 后面直接跟参数就是指定层的满足条件的文件输出

demo

dingmac@php_test$ find ./ -name 'test*' -d 1 -print
.//test.php
.//test1.php
.//test_2.php
.//test_global.php
.//testone
dingmac@php_test$ find ./ -name 'test*' -d 2 -print
.//testone/test1.txt
.//testone/test2.txt
dingmac@php_test$ find ./ -name 'test*' -d 3 -print
dingmac@php_test$ find ./ -name 'test*' -d 4 -print
dingmac@php_test$ find ./ -name 'test*' -d 5 -print
.//testone/first/second/third/testwow.txt

再查看一个 mindepth 的例子 指定最少深度

dingmac@php_test$ find ./ -name 'test*' -mindepth 1 -print
.//test.php
.//test1.php
.//test_2.php
.//test_global.php
.//testone
.//testone/first/second/third/testwow.txt
.//testone/test1.txt
.//testone/test2.txt
dingmac@php_test$ find ./ -name 'test*' -mindepth 2 -print
.//testone/first/second/third/testwow.txt
.//testone/test1.txt
.//testone/test2.txt
dingmac@php_test$ find ./ -name 'test*' -mindepth 3 -print
.//testone/first/second/third/testwow.txt

参考 http://www.binarytides.com/linux-find-command-examples/ https://kb.iu.edu/d/admm

相同的可以使用-maxdepth 用来表示最大深度 demo find -name "*test* -maxdepth 2" 查找最深是2的文件

如果想取非,使用 ! 表示非 demo find -name "*test*" 查找文件中不包含 test 的文件

连字符 包含 -a -o ! 两个不带任何参数的时候默认是 “并”

-perm 补充

参考

http://www.cnblogs.com/gaojian/archive/2013/01/25/2876046.html
https://www.computerhope.com/unix/ufind.htm

我百度了一下 出现的各种帖子都是只给个例子 比如

find ./ -perm 666 这样的命令 就算把-perm 这个参数讲了 要不然就列几个例子 笼统的说明一下,更深的就没有了

所以下面在整理一下 -perm 这个参数的使用

mac 中 man find 找到 -perm 可以自己研究,mac是unix核和linux 优点差别

-perm 参数支持好几种方式

  1. -perm mode 精确匹配 差一点都不行

    可以使用数字表示和字符表示 demo:

    find . -perm 642 
    ./timg.gif # 结果
    
    find . -perm u=rw,g=r,o=w #和上面结果一样使用","连接 也是精确查找642
  2. -perm -mode 包含就可以 比如 110 010 010 [622] 比如 有个文件的权限是 110 101 110 [656] 是无法被圈的 110 011 110 [634] 可以查找到

    demo:

    dingmac@linux_test$ ll
    total 8
    drwxr-xr-x   5 dingmac  staff   170B  9 13 18:38 ./
    drwx------+ 37 dingmac  staff   1.2K  9 17 22:37 ../
    -rw-r-xrw-   1 dingmac  staff     0B  9 13 17:23 file1.txt*
    -rw--wxr--   1 dingmac  staff     0B  9 13 17:23 file2.txt*
    -rwxr-xr-x   1 dingmac  staff    44B  9 13 18:38 list_user.awk*
    dingmac@linux_test$ find . -perm 642
    dingmac@linux_test$ find . -perm -642
    ./file1.txt
    
    #如果要使用rwx 字符表示 和上面的一样
    find ./ -perm -u=rw,g=r,o=w
    # 出来的结果和上面一样
    # 注意的是只需要在 第一个上面加 - 就可以了
    
    另外需要说明的是 -u=rw,g=r,o=w 这里面的 “=”
    同样可以有+- 替代
    = 表示含有 + 表示大于或者比这个高 其实和 = 没多大差别 - 表示低于都可以 其实 - 没有啥意义 理解上 = + 一个意思就可以了
    
    所以 下面两个命令是一样的
    
    dingmac@linux_test$ find ./ -perm -u+rw,g+x,o+rw
    .//file1.txt
    dingmac@linux_test$ find ./ -perm -u=rw,g=x,o=rw
    .//file1.txt

-perm +mode 其实是一个与或概念 1 xor 1 = 1 1 xor 0 = 0 0 xor 0 = 0

如果我们要查找 g 有写权限的文件 比如下面这个文件 将不被筛选 100 100 101 [445] 下面是例子

dingmac@linux_test$ ll
total 8
drwxr-xr-x   5 dingmac  staff   170B  9 13 18:38 ./
drwx------+ 37 dingmac  staff   1.2K  9 17 22:37 ../
-r--r--r-x   1 dingmac  staff     0B  9 13 17:23 file1.txt*
-rw--wxr--   1 dingmac  staff     0B  9 13 17:23 file2.txt*
-rwxr-xr-x   1 dingmac  staff    44B  9 13 18:38 list_user.awk*
dingmac@linux_test$ find . -perm +g=x
.
./file2.txt
./list_user.awk
dingmac@linux_test$ find . -perm +g+x
.
./file2.txt
./list_user.awk

linux 系统中还有一个 /mode 类似于 mac 中的 +

其他的就没啥

补充1

查找符合条件的文件,按照大小排序

需要用到命令有 find 还有sort 但是有一个问题想要获得 human readble 的方式显示就会有问题

demo 查看列表

dingmac@php_test$ find . -name "*test*" -type f -exec ls -al {} ; | sort -k 5 -nr
-rw-r--r--  1 dingmac  staff  18696  9 20 12:16 ./awk_test.txt
-rw-r--r--@ 1 dingmac  staff  1038  9 19 17:40 ./test_2.php
-rw-r--r--@ 1 dingmac  staff  407  9 19 15:59 ./test.php
-rw-r--r--  1 dingmac  staff  272  9 14 15:20 ./test1.php
-rw-r--r--  1 dingmac  staff  77  9 18 14:05 ./test_global.php
-rw-r--r--  1 dingmac  staff  0  9 20 23:05 ./testone/first/second/third/testwow.txt
-rw-r--r--  1 dingmac  staff  0  9 20 22:01 ./testone/test2.txt
-rw-r--r--  1 dingmac  staff  0  9 20 22:01 ./testone/test1.txt

但是想看到human readable的形式就不能按照上面的方法

我尝试过下面的方法 我发现ls 命令中有一个参数 -S 是按照size 倒序排列的

demo

dingmac@php_test$ ls -alShd  test*
-rw-r--r--@ 1 dingmac  staff   1.0K  9 19 17:40 test_2.php
-rw-r--r--@ 1 dingmac  staff   407B  9 19 15:59 test.php
-rw-r--r--  1 dingmac  staff   272B  9 14 15:20 test1.php
drwxr-xr-x  6 dingmac  staff   204B  9 20 23:05 testone
-rw-r--r--  1 dingmac  staff    77B  9 18 14:05 test_global.php

是ok的 -d 的命令是将文档当做文件处理 不循环列出下面的文件

但是在find命令 中使用的时候会有问题下面是demo

dingmac@php_test$ find . -name "*test*" -type f -exec ls -alSh {} ; 
-rw-r--r--  1 dingmac  staff    18K  9 20 12:16 ./awk_test.txt
-rw-r--r--@ 1 dingmac  staff   407B  9 19 15:59 ./test.php
-rw-r--r--  1 dingmac  staff   272B  9 14 15:20 ./test1.php
-rw-r--r--@ 1 dingmac  staff   1.0K  9 19 17:40 ./test_2.php
-rw-r--r--  1 dingmac  staff    77B  9 18 14:05 ./test_global.php
-rw-r--r--  1 dingmac  staff     0B  9 20 23:05 ./testone/first/second/third/testwow.txt
-rw-r--r--  1 dingmac  staff     0B  9 20 22:01 ./testone/test1.txt
-rw-r--r--  1 dingmac  staff     0B  9 20 22:01 ./testone/test2.txt

上面就完全出错误了

暂时没有找到合适的方法

找到一个 可行版本 https://askubuntu.com/questions/80244/how-do-i-sort-by-human-readable-sizes-numerically

但要自己写

终于找到了方法 下面是demo

dingmac@php_test$ find . -type f -name "*test*" -exec  ls -lShr {} +
-rw-r--r--  1 dingmac  staff     0B  9 20 22:01 ./testone/test2.txt
-rw-r--r--  1 dingmac  staff     0B  9 20 22:01 ./testone/test1.txt
-rw-r--r--  1 dingmac  staff     0B  9 20 23:05 ./testone/first/second/third/testwow.txt
-rw-r--r--  1 dingmac  staff    77B  9 18 14:05 ./test_global.php
-rw-r--r--  1 dingmac  staff   272B  9 14 15:20 ./test1.php
-rw-r--r--@ 1 dingmac  staff   407B  9 19 15:59 ./test.php
-rw-r--r--@ 1 dingmac  staff   1.0K  9 19 17:40 ./test_2.php
-rw-r--r--  1 dingmac  staff    18K  9 20 12:16 ./awk_test.txt

关键是 “+”

慢慢沉淀自己
原文地址:https://www.cnblogs.com/martinding/p/7565601.html