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

Andrey Fedorov picture Andrey Fedorov · Feb 12, 2009 · Viewed 70.1k times · Source

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; )

Answer

Petr Kozelka picture Petr Kozelka · Dec 6, 2014

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