显示所有没有任何子目录的文件夹

显示所有没有任何子目录的文件夹

如何使用终端显示所有没有任何子目录的文件夹?

答案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

相关内容