breadth-first option in the Linux `find' utility?
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 ofREPLY
after running the code here in quotes for each match withREPLY
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.
Nope
Go to this question on SO for workarounds.
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.
#!/bin/bash depth=0 while find -mindepth $depth -maxdepth $depth | grep '.' do depth=$((depth + 1)) done
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...