如何recursion列出一个位置的所有目录,宽度优先?

广度优先列表在这里很重要。 此外,限制search的深度将是很好的。

$ find . -type d /foo /foo/subfoo /foo/subfoo/subsub /foo/subfoo/subsub/subsubsub /bar /bar/subbar $ find . -type d -depth /foo/subfoo/subsub/subsubsub /foo/subfoo/subsub /foo/subfoo /foo /bar/subbar /bar $ < what goes here? > /foo /bar /foo/subfoo /bar/subbar /foo/subfoo/subsub /foo/subfoo/subsub/subsubsub 

如果可能的话,我想用bash单线程来做这个。 如果有一个JavaScript的shell,我会想像的东西

 bash("find . -type d").sort( function (x) x.findall(/\//g).length; ) 

find命令支持-printf选项,它可以识别很多占位符。

一个这样的占位符是%d ,它呈现给定路径的深度,相对于开始的位置。

因此,您可以使用以下简单的一行:

 find -type d -printf '%d\t%P\n' | sort -r -nk1 | cut -f2- 

这是相当简单的,并不依赖像perl这样的重工具。

怎么运行的:

  • 它在内部生成文件列表,每个文件呈现为双字段行
  • 第一个字段包含用于(反向)数字排序的深度,然后切除
  • 结果是简单的文件列表,每行一个文件,以最深的顺序

如果你想使用标准工具来做,下面的管道应该工作:

 find . -type d | perl -lne 'print tr:/::, " $_"' | sort -n | cut -d' ' -f2 

那是,

  1. 首先在这里查找并打印所有目录
  2. 计算每个目录中斜杠的数量并将其预先加到路径中
  3. 按深度排序(即,斜杠数量)
  4. 只提取路径。

要限制找到的深度,请将-maxdepth参数添加到find命令。

如果您想要以相同顺序列出的目录中查找输出,请使用“sort -n -s”而不是“sort -n”。 “-s”标志使排序稳定(即,在相同比较的项目之间保留输入顺序)。

我的感觉是,这是比以前提到的更好的解决方案。 它涉及grep和这样一个循环,但我觉得它工作得很好,特别是对于你想要的东西行缓冲,而不是完整的发现缓冲。

这是更加资源密集的,因为:

  • 很多分叉
  • 很多发现
  • 当前深度之前的每个目录被查找的次数与文件结构的总深度相同(如果实际上有任何内存量,这应该不成问题)

这是很好的,因为:

  • 它使用bash和基本的GNU工具
  • 它可以被破坏,只要你想要(就像你看到你正在寻找飞行)
  • 它每行工作,而不是每个查找,所以后续命令不必等待查找和排序
  • 它的工作原理是基于实际的文件系统分离,所以如果你有一个斜线的目录,它将不会比它更深; 如果你有一个不同的路径分隔符配置,你仍然没事。
  #!/斌/庆典 
深度= 0

同时找到-mindepth $ depth -maxdepth $ depth |  grep'。
做
     depth = $((depth + 1))
 DONE 

你也可以很容易地把它合理地放在一行上:

 depth=0; while find -mindepth $depth -maxdepth $depth | grep --color=never '.'; do depth=$((depth + 1)); done 

但是我更喜欢小键盘输入

我不认为你可以使用内置实用程序来完成,因为在遍历目录层次结构时,你几乎总是需要自上而下或自下而上的深度优先搜索。 这是一个Python脚本,它会给你一个广度优先的搜索:

 import os, sys rootdir = sys.argv[1] queue = [rootdir] while queue: file = queue.pop(0) print(file) if os.path.isdir(file): queue.extend(os.path.join(file,x) for x in os.listdir(file)) 

编辑:

  1. 使用os.path -module代替os.statstat -module。
  2. 使用list.poplist.extend代替del+=运算符。

我试图找到一种方法来做到这一点,但它似乎没有任何像-breadth选项。 为它写一个补丁,尝试下面的shell咒语(bash):

 LIST="$(find . -mindepth 1 -maxdepth 1 -type d)"; while test -n "$LIST"; do for F in $LIST; do echo $F; test -d "$F" && NLIST="$NLIST $(find $F -maxdepth 1 -mindepth 1 -type d)"; done; LIST=$NLIST; NLIST=""; done 

我偶然发现了这种情况,所以我不知道它是否能够正常工作(我只是在你所问的特定目录结构上进行测试)

如果你想限制深度,在外部循环中加一个计数器变量,就像这样(我也在给这个加注释):

 # initialize the list of subdirectories being processed LIST="$(find . -mindepth 1 -maxdepth 1 -type d)"; # initialize the depth counter to 0 let i=0; # as long as there are more subdirectories to process and we haven't hit the max depth while test "$i" -lt 2 -a -n "$LIST"; do # increment the depth counter let i++; # for each subdirectory in the current list for F in $LIST; do # print it echo $F; # double-check that it is indeed a directory, and if so # append its contents to the list for the next level test -d "$F" && NLIST="$NLIST $(find $F -maxdepth 1 -mindepth 1 -type d)"; done; # set the current list equal to the next level's list LIST=$NLIST; # clear the next level's list NLIST=""; done 

(用深度替换2 in -lt 2

基本上这实现了标准的广度优先搜索算法,使用$LIST$NLIST作为目录名称的队列。 这是后一种方法,作为一个简单的复制和粘贴的方式:

 LIST="$(find . -mindepth 1 -maxdepth 1 -type d)"; let i=0; while test "$i" -lt 2 -a -n "$LIST"; do let i++; for F in $LIST; do echo $F; test -d "$F" && NLIST="$NLIST $(find $F -maxdepth 1 -mindepth 1 -type d)"; done; LIST=$NLIST; NLIST=""; done 

没有理所当然的排序:find -maxdepth -type d

为了得到应有的顺序,你必须自己做这个递归:

 #!/bin/bash r () { let level=$3+1 if [ $level -gt $4 ]; then return 0; fi cd "$1" for d in *; do if [ -d "$d" ]; then echo $2/$d fi; done for d in *; do if [ -d "$d" ]; then (r "$d" "$2/$d" $level $4) fi; done } r "$1" "$1" 0 "$2" 

然后你可以调用这个脚本参数的基础目录和深度。

你可以使用find命令,找到/ path / to / dir -type d那么下面的例子就是当前目录中的目录列表:

 find . -type d 

这是一个可能的方式,使用find。 我还没有彻底测试过,所以用户要小心…

 depth=0 output=$(find . -mindepth $depth -maxdepth $depth -type d | sort); until [[ ${#output} -eq 0 ]]; do echo "$output" let depth=$depth+1 output=$(find . -mindepth $depth -maxdepth $depth -type d | sort) done 

像这样的东西:

 find . -type d | perl -lne'push @_, $_; print join $/, sort { length $a <=> length $b || $a cmp $b } @_ if eof'