Mao*_*oPU 5 linux command-line
如何只列出没有另一个子目录的目录?
想象一个像/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帮助(我无法让它按照我想要的方式做出反应)?
这是一个符合 POSIX 的解决方案,它对 的输出进行后处理find以删除具有列出的子目录的目录。它假定目录名称中没有换行符。
{ find . -type d; echo; } |
awk 'index($0,prev"/")!=1 && NR!=1 {print prev}
1 {sub(/\/$/,""); prev=$0}'
Run Code Online (Sandbox Code Playgroud)
说明:awk 脚本会延迟每一行的打印,直到它读取下一行,并且如果它不是前缀,则只打印上一行。这利用了在find其父目录之后立即列出子目录的事实。额外的"/"是避免foo在foobar也存在时虚假删除。不优雅NR!=1避免打印初始空行,不优雅echo;是不要对最后一行有同样不优雅的特殊情况。调用sub从顶级目录中删除尾部斜杠,以防 egfind ./被调用。
像往常一样,有一个神秘的 zsh one-liner。
echo **/.(e\''test -z $REPLY/*(/DN[1])'\':h)
Run Code Online (Sandbox Code Playgroud)
更长、更易读的版本:
is_leaf () { [ -z $REPLY/*(/DN[1]) ] }
echo **/.(+is_leaf:h)
Run Code Online (Sandbox Code Playgroud)
最后一行可以简化为echo **/(+is_leaf),如果你不”介意尾随/。
摘要说明:括号中的内容是glob qualifiers,记录在zshexpn手册页中。我们过滤 glob 的结果**/(扩展到当前目录及其所有子目录),只保留那些函数is_leaf(或 之间的代码'…')返回 0 的结果。过滤器代码 globs 正在测试的匹配项的子目录$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:) }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6981 次 |
| 最近记录: |