2009-10-15 41 views
13

有没有一种简单的方法可以在Linux中只列出给定目录下的目录? 为了更好地解释,我可以这样做:在Linux中列出所有的叶子目录

find mydir -type d 

这给:

mydir/src 
mydir/src/main 
mydir/bin 
mydir/bin/classes 

我想的却是:

mydir/src/main 
mydir/bin/classes 

我可以在遍历一个bash脚本做到这一点线和删除前一行,如果下一行包含路径,但我想知道是否有一个更简单的方法,不使用bash循环。

+0

你的榜样,'找到mydir的-mindepth 2 - 类型d'可以工作,但是当你有多个最大深度时它不会。你是否真的只想列出不包含其他目录的目录,或者你是否希望看到特定级别的目录结构? – Cascabel 2009-10-15 19:17:54

+0

是的,谢谢澄清 - 我的例子是一个简单的例子。我的确在寻求更为一般的解决方案。 此外,我期待看到一般的目录结构,并不真正关心目录中的文件(所以叶也就意味着在这个上下文中的“叶目录”)。谢谢。 – amol 2009-10-15 21:09:38

回答

10
find . -type d | sort | awk '$0 !~ last "/" {print last} {last=$0} END {print last}' 
+0

谢谢,只是我寻找的解决方案:) – amol 2009-10-15 21:02:11

+0

这将产生正确的,但未排序的结果,而不'排序'(所以你可以把它放在最后,而不是,如果你想)。 – 2009-10-16 05:16:57

+0

如果您有两个目录:foo/bar和foo/bar_baz,则这不起作用。 foo/bar不会被打印。 – mattismyname 2012-08-07 19:43:45

4

我想不出没有循环的任何事情。所以,这里有一些循环:

显示当前目录下的叶目录,无论其深度:

for dir in $(find -depth -type d); do [[ ! $prev =~ $dir ]] && echo "$dir" ; prev="$dir"; done 

这个版本正确处理目录名称包含空格:

saveIFS=$IFS; IFS=$'\n'; for dir in $(find -depth -type d); do [[ ! $prev =~ $dir ]] && echo "${dir}" ; prev="$dir"; done; IFS=$saveIFS 

这里是一款使用Jefromi的建议:

find -depth -type d | while read dir; do [[ ! $prev =~ $dir ]] && echo "${dir}" ; prev="$dir"; done 
+0

OP询问是否有比循环输出更简单的方法,而不是如何编写循环。也就是说,使用'find .... |也是一个好主意而在$(...)'中读取dir而不是'dir',因为它不必在打印任何内容之前完成整个查找。 – Cascabel 2009-10-15 19:29:53

+0

@Jefromi:将'find'换成'while'也可以免费处理空格。 – 2009-10-15 19:46:34

+0

那么,避免循环显然不是一个难的“要求”,但我希望有一个更简单+直观的方式来做到没有循环。感谢您的查找|虽然信息。 – amol 2009-10-15 21:01:40

0

这仍然是一个循环,因为它在sed使用分支命令:

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

基于在info sed(uniq的工作一样)的脚本。

编辑这里是sed脚本注释爆发(从info sed复制和修改):

# copy the pattern space to the hold space 
h 

# label for branch (goto) command 
:b 
# on the last line ($) goto the end of 
# the script (b with no label), print and exit 
$b 
# append the next line to the pattern space (it now contains line1\nline2 
N 
# if the pattern space matches line1 with the last slash and whatever comes after 
# it followed by a newline followed by a copy of the part before the last slash 
# in other words line2 is different from line one with the last dir removed 
# see below for the regex 
/^\(.*\)\/.*\n\1$/ { 
    # Undo the effect of 
    # the n command by copying the hold space back to the pattern space 
    g 
    # branch to label b (so now line2 is playing the role of line1 
    bb 
} 
# If the `N' command had added the last line, print and exit 
# (if this is the last line then swap the hold space and pattern space 
# and goto the end (b without a label) 
$ { x; b } 

# The lines are different; print the first and go 
# back working on the second. 
# print up to the first newline of the pattern space 
P 
# delete up to the first newline in the pattern space, the remainder, if any, 
# will become line1, go to the top of the loop 
D 

这里是正则表达式是这样做的:

  • / - 启动模式
  • ^ - 匹配行首
  • \( - 启动捕获组(返回参考子表达式)
  • .* - 零个或多个(*)任意字符(。)
  • \) - 端捕获组
  • \/ - 一斜杠(/)(其中\转义)
  • .* - 零个或多个任意字符
  • \n - 一个新行
  • \1 - 副本(在这种情况下,无论是在行的开头和最后一个斜杠之间)
  • $ - 匹配行尾
  • / - 结束模式
+0

您的建议工作得很好,但我觉得很难理解。不过谢谢,我会试着弄清楚sed选项的含义。 – amol 2009-10-15 21:05:12

0

我觉得你可以看看所有的目录,然后重定向输出中,并使用xargs的计数数量文件每个子目录,当没有子目录(xargs的发现SUBDIR型d | wc -l ...类似的东西,我现在无法测试)你找到了一片叶子。

虽然这仍然是一个循环。

+0

嗯..也许我没有解释什么“叶子”意思是非常正确的,我的意思是“叶子尖”,所以如果所有的目录都是文件,它仍然可以作为我的问题的一个“叶子”。 – amol 2009-10-15 20:57:41

+0

ouhla, m累了,我你在寻找目录下和wc -l == 0,那应该是诀窍...... – LB40 2009-10-15 20:59:47

4

如果你正在寻找可视化的东西,tree -d是不错的。

 
drinks 
|-- coke 
| |-- cherry 
| `-- diet 
|  |-- caffeine-free 
|  `-- cherry 
|-- juice 
| `-- orange 
|  `-- homestyle 
|   `-- quart 
`-- pepsi 
    |-- clear 
    `-- diet 
+0

谢谢,这也很有用(不是为我目前的问题,但很高兴知道) 我想知道,树是最近添加?我记得大约一年前需要类似这样的东西(当时在RHEL上,现在在Ubuntu上),最后在http://centerkey.com/tree上使用脚本。 – amol 2009-10-16 20:33:03

10

如果你想只有叶目录(不包含任何子目录目录),看看this other question。答案也explains it,但总之它是:

find . -type d -links 2 
+1

至少在Mac上,链接包括当前,父目录和子目录以及文件。所以这个解决方案只适用于空叶子目录。 – 2012-03-02 13:46:03

+0

我刚刚注意到它在SMB挂载上也不起作用。但它在NFS挂载上。但是在工作的地方(本地或NFS Linux目录),它肯定是最简单的解决方案。 – mivk 2012-04-08 17:17:30

0

试试下面的一行代码(在Linux & OS X测试):

find . -type d -execdir sh -c 'test -z "$(find "{}" -mindepth 1 -type d)" && echo $PWD/{}' \; 
相关问题