Is there any breadth-first/depth-first option in the Linux `find' utility?


There's nothing built-in to find, even GNU find. You can postprocess the output of find to sort by number of slashes, for example with Perl:

find ... | perl -e 'print sort {$a=~s!/!/! <=> $b=~s!/!/!} <>'
  • <> is the list of all input lines;
  • $a =~ s!/!/!g is the number of slashes in $a, which we use as the sort criterion.

If you can use zsh:

echo **/*(oe\''REPLY=${REPLY//[^\/]}'\')
  • **/* lists all files in the current directory and subdirectories.
  • The stuff inside the parentheses is a glob qualifier.
  • The glob qualifier oe controls the order in which matches are returned: they are sorted by the value of REPLY after running the code here in quotes for each match with REPLY initially set to the matched path.
  • Said code transforms $REPLY to delete everything except slashes. So the result consists of everything at depth 1 (empty resulting $REPLY), then everything at depth 2 ($REPLY ends up to be /), depth 3 (//), etc.
|improve this answer|||||
  • 1
    The sort post process is very interesting, however, sort needs the find to be completed, and you won't have chance to control break. – Xiè Jìléi Oct 1 '10 at 7:49


Go to this question on SO for workarounds.

|improve this answer|||||

My feeling is that you can. It involves grep and such and a loop, but I find it works very well, specifically for your case about the find not needing to be completed.

It is more resource intensive because of:

  • Lots of forking
  • Lots of finds
  • Each directory before the current depth is hit by find as many times as there is total depth to the file structure (this shouldn't be a problem if you have practically any amount of ram...)

This is good because:

  • It uses bash and basic gnu tools
  • It can be broken whenever you want (like you see what you were looking for fly by)
  • It works per line and not per find, so subsequent commands don't have to wait for a find and a sort
  • It works based on the actual file system separation, so if you have a directory with a slash in it, it won't be listed deeper than it is; if you have a different path separator configured, you still are fine.

while find -mindepth $depth -maxdepth $depth | grep '.'
    depth=$((depth + 1))

You can also fit it onto one line fairly(?) easily:

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

But I prefer small scripts over typing...

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.