如何使用终端显示所有没有任何子目录的文件夹?
答案1
你可以做一个 find-within-a-find 例如
find . -type d -exec bash -c '
[[ -z $(find "$1" -mindepth 1 -type d -print -quit) ]] && printf "%s\n" "$1"
' bash {} \;
如果你不想要前导路径组件,那么
find . -type d -exec bash -c '
[[ -z $(find "$1" -mindepth 1 -type d -print -quit) ]] && printf "%s\n" "${1##*/}"
' bash {} \;
我不禁觉得应该有一个“聪明”的方法来做到这一点-depth
答案2
尝试这个:
find . -type d -print0 | sort -z | gawk '{a[$0]; sub(/[/][^/]*$/, ""); if ($0 in a) delete a[$0]} END{for (d in a)print d}' RS='\0'
怎么运行的
为了确保所有可能的目录名称的安全,我们对管道的每个步骤使用以 nul 分隔的列表。
find . -type d -print0
这将获取当前目录的所有子目录的列表。
sort -z
这会对目录进行排序,其效果是将子目录放在其父目录之后。
gawk '{a[$0]; sub(/[/][^/]*$/, ""); if ($0 in a) delete a[$0]} END{for (d in a)print d}' RS='\0'
这会将目录列表放入关联数组中。对于添加的每个目录,它会检查目录父级是否在数组中。如果在,它会将其从数组中删除。让我们一步一步来看:
a[$0]
这会将当前记录中命名的目录添加为数组中的键
a
。(我们没有为其分配值,因为我们不需要值。)sub(/[/][^/]*$/, "")
这将删除最后一个子目录,
$0
以便$0
现在引用父目录。if ($0 in a) delete a[$0]
如果父目录是中的键
a
,那么我们将其删除。END{for (d in a) print d}
这将打印出我们未找到子目录的每个目录。(由于 awk 数组的工作方式,输出没有特定的顺序。)
RS='\0'
这告诉 awk 期望以 nul 分隔的输入。换句话说,在输入时,awk 使用 nul 字符作为记录分隔符。
例子
让我们创建一些目录,然后验证输出是否仅列出没有子目录的目录:
$ mkdir -p a/b/c/x1 a/b/c/x2 a/b/x3 a/x4
$ find . -type d -print0 | sort -z | gawk '{a[$0]; sub(/[/][^/]*$/, ""); if ($0 in a) delete a[$0]} END{for (d in a)print d}' RS='\0'
./a/x4
./a/b/x3
./a/b/c/x1
./a/b/c/x2
变化:仅打印目录的基本名称
find . -type d -print0 | sort -z | gawk '{a[$0]; sub(/[/][^/]*$/, ""); if ($0 in a) delete a[$0]} END{for (d in a) {sub(/^.*[/]/,"",d); print d}}' RS='\0'
为了说明,让我们针对与上面相同的目录运行它:
$ find . -type d -print0 | sort -z | gawk '{a[$0]; sub(/[/][^/]*$/, ""); if ($0 in a) delete a[$0]} END{for (d in a) {sub(/^.*[/]/,"",d); print d}}' RS='\0'
x5
x4
x3
x1
x2