使用“查找”仅列出没有更多子目录的目录

使用“查找”仅列出没有更多子目录的目录

如何才能列出没有其他子目录的目录?

/A /A/AA /A/AB /A/AB/ABB /B /C /C/CC /C/CC/CCC /C/CC/CCC/CCCC想象一个我想用来find列出的结构/A/AA /A/AB/ABB /B /C/CC/CCC/CCCC

起点应该是find . -type d,但都-mindepth不能-maxdepth使用,能有-noleaf帮助吗(我无法让它按照我想要的方式做出反应)?

答案1

这是一个符合 POSIX 的解决方案,它对输出进行后处理find以删除具有列出的子目录的目录。它假定目录名称中没有换行符。

{ find . -type d; echo; } |
awk 'index($0,prev"/")!=1 && NR!=1 {print prev}
     1 {sub(/\/$/,""); prev=$0}'

解释:awk 脚本会延迟打印每一行,直到读取下一行为止,并且仅在前一行不是前缀时才打印前一行。这利用了find列出父级目录后立即列出子目录的事实。额外的"/"是为了避免错误地删除foofoobar存在的目录。不雅之处NR!=1是避免打印初始空行,不雅之echo;处是最后一行没有同样不雅的特殊情况。调用会sub从顶层目录中删除尾部斜杠,以防find ./调用 eg。


和平常一样,有一个神秘的 zsh 单行命令。

echo **/.(e\''test -z $REPLY/*(/DN[1])'\':h)

更长、更易读的版本:

is_leaf () { [ -z $REPLY/*(/DN[1]) ] }
echo **/.(+is_leaf:h)

echo **/(+is_leaf)如果您不介意结尾的,最后一行可以简化为/

摘要解释:括号里的内容是glob 限定符,在zshexpn手册页中有记录。我们过滤 glob 的结果**/(扩展到当前目录及其所有子目录),仅保留函数is_leaf(或 之间的代码'…')返回 0 的结果。过滤器代码将匹配项测试的子目录($REPLY)全部匹配(实际上,[1]使其在第一个子目录后停止)并返回一个状态,指示是否至少找到一个子目录。 glob 限定符/将扩展限制为目录;N表示如果没有匹配项,则扩展为空;D导致包含点文件;:h是历史修饰符并导致/.后缀被剥离(一般来说,它意味着dirname)。

为了说明 zsh 的 glob 限定符的可能性,这里还有另外两个变体(更长而且我认为更晦涩)及其相应的is_leaf功能:

echo **/.(e\''tmp=($REPLY/*(/DN[1])); ((!#tmp))'\':h)
echo **/.(e\''$REPLY/*(/DN[1]e:REPLY=false:)'\':h)
is_leaf () { set -- $REPLY/*(/DN[1]); ((!#)); }
is_leaf () { return $REPLY/*(/DN[1]e:REPLY=1:) }

答案2

这是我使用的:

leaf () { find "${1:-.}" -depth -type d | sed  'h; :b; $b; N; /^\(.*\)\/.*\n\1$/ { g; bb }; $ {x; b}; P; D'; }

使用起始目录来调用它:

leaf /start/dir

答案3

查找没有子目录的目录:

find dir -type d -links 2

解释:一个目录包含指向其每个子目录的链接、来自其父目录的链接和指向其自身的链接,因此,如果没有子目录,则链接数为 2。

相关内容