如何在find命令中排除当前目录或点文件夹的"类型为d"结果?

259
find . -type d

可以用来查找某个起始点下的所有目录。但它也会返回当前目录 (.),这可能是不想要的。如何排除它?

5个回答

292

-maxdepth参数可以控制find函数的递归深度,而相应的-mindepth参数也可以限制从“顶部”开始的深度。因此,实际需要的是:

find . -mindepth 1 -type d

7
这段话的意思是,“它适用于GNU find,但不幸的是这是POSIX 7 find的GNU扩展,即使LSB也使用POSIX shell工具而非GNU扩展工具。” - Ciro Santilli OurBigBook.com
16
这对我起了作用。具体而言:find . -mindepth 1 -maxdepth 1 -type d ... - racl101

243

POSIX 7方案:

find . ! -path . -type d
对于这种情况( . ),高尔夫球比 mindepth 解决方案更好(24比26个字符),尽管由于!的缘故,可能会稍微难打一些。
为了排除其他目录,这种高尔夫球技巧就不那么有效,并且需要一个变量来保持DRY。
D="long_name"
find "$D" ! -path "$D" -type d

!-mindepth之间,我的决策树:

  • 脚本?选择!以保证可移植性。
  • GNU上的交互式会话?
    • 排除.?掷硬币。
    • 排除long_name?使用-mindepth

如果你需要排除多个路径,只需使用以下命令:find /path/ ! -path "/path/first" ! -path "/path/second",这是唯一的方法吗? - Vincent De Smet
2
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Ciro Santilli OurBigBook.com
我的问题如下:我想要递归删除目录中除一个子目录之外的所有内容。我使用 findgrep 来排除该目录,但父目录仍然存在,导致最终删除了所有内容。 - Vincent De Smet
@VincentDeSmet 我没有看到使用 find 的直接解决方案,你需要检查前缀:https://dev59.com/emMl5IYBdhLWcg3w_rKD 但是 Bash for 循环可以处理它 :-) - Ciro Santilli OurBigBook.com
你可能想要转义感叹号字符(\!)以保险起见。我机器上的man find中的所有示例都已经转义了,因此这似乎很可能是个好主意™。编辑-刚刚注意到它甚至明确表示:“如果表达式为false,则! expr为True。通常还需要保护此字符免受shell解释。” - Adrian Günter
显示剩余5条评论

24

当我不介意忽略一级点文件(在bash中,通过 * 无法匹配这些文件 - 可以参考shopt内置的“dotglob”选项:https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html),我会使用 find ./* <...>

eclipse tmp # find .
.
./screen
./screen/.testfile2
./.X11-unix
./.ICE-unix
./tmux-0
./tmux-0/default
eclipse tmp # find ./*
./screen
./screen/.testfile2
./tmux-0
./tmux-0/default

请注意,不要在使用“-exec”选项时使用此技巧。例如,如果您尝试执行以下命令:find dir/* -type d -exec rmdir {} \;,将会出现错误。 - plhn
你可能误解了或者被错误指导了。那个命令是可以正常工作的。如果你看到错误信息,那很可能是来自于 rmdir 命令,并且告诉你这些目录不是空的,因为 find 命令会进行深度优先搜索,先显示父目录再显示子目录。 - Milos Ivanovic
4
注意: “忽略第一级点文件”也意味着排除所有隐藏的文件/目录。 - Jonathan H

6

好的,还有一个简单的解决方法(对于我来说,解决方案在Windows git bash上无法正常工作)

find * -type d

它可能不是非常高效,但可以完成工作,有时我们需要它。

[编辑] :如@AlexanderMills所评论的那样,它将不会显示根位置的隐藏目录(例如./.hidden),但它将显示隐藏的子目录(例如./folder/.hiddenSub)。[在Windows上使用git bash测试过]


1
在此之前使用 shopt -s dotglob 命令,你将匹配到除了当前文件夹的所有点文件。 已在 bash 版本 3.2 和 5.0 上测试通过。 - MetalGodwin

0
将其管道传输到sed。不要忘记-r扩展正则表达式。
find . -type d | sed -r '/^\.$/d'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接