How do I recursively list all directories at a location, breadth-first?


Question

Breadth-first list is important, here. Also, limiting the depth searched would be nice.

$ 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

I'd like to do this using a bash one-liner, if possible. If there were a javascript-shell, I'd imagine something like

bash("find . -type d").sort( function (x) x.findall(/\//g).length; )
1
28
2/12/2009 4:11:21 AM

Accepted Answer

The find command supports -printf option which recognizes a lot of placeholders.

One such placeholder is %d which renders the depth of given path, relative to where find started.

Therefore you can use following simple one-liner:

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

It is quite straightforward, and does not depend on heavy tooling like perl.

How it works:

  • it internally generates list of files, each rendered as a two-field line
  • the first field contains the depth, which is used for (reverse) numerical sorting, and then cut away
  • resulting is simple file listing, one file per line, in the deepest-first order
28
12/6/2014 9:08:01 PM

If you want to do it using standard tools, the following pipeline should work:

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

That is,

  1. find and print all the directories here in depth first order
  2. count the number of slashes in each directory and prepend it to the path
  3. sort by depth (i.e., number of slashes)
  4. extract just the path.

To limit the depth found, add the -maxdepth argument to the find command.

If you want the directories listed in the same order that find output them, use "sort -n -s" instead of "sort -n"; the "-s" flag stabilizes the sort (i.e., preserves input order among items that compare equally).


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon