find plus grep
Combine find to traverse directories recursively with grep.
If support for -print0 and -0 are compiled in, then you can use xargs to invoke grep for many files at once¹:
find /some/dir -type f -print0 | xargs -0 grep -H PATTERN
If your file names are tame (no whitespace or \'"), you don't need -print0/-0:
find /some/dir -type f |xargs grep -H PATTERN
If you have no suitable xargs, you'll need to invoke grep on each file name separately:
find /some/dir -type f -exec grep -H PATTERN {} \;
If you have find but it doesn't have -exec, and your file names are tame (no newlines or \[*?), and your shell supports command substitutions (i.e. ash and not hush), and there aren't too many files to consider, you can generate the list of file names with find and pass that as an argument to grep.
set -f
IFS='
'
grep PATTERN $(find /some/dir -type f)
set +f
If there are many files, you can use a for loop over all the files (still ash-only because of the command substitution).
set -f
IFS='
'
for x in $(find /some/dir -type f); do
grep -H PATTERN "$x"
done
set +f
¹ No -exec … + on Busybox.
Without find
If you don't have find, it gets complicated. If your Busybox has ash and a decent test, you can write a recursive directory traversal in the shell.
traverse () {
d=$1; shift
for x in "$d"/* "$d"/.[!.]* "$d"/..?*; do
if test -f "$x"; then
"$@" "$x"
elif test -d "$x"; then
traverse "$x" "$@"
fi
done
}
traverse /some/dir
But if you don't have find, you're probably on a very limited system where the shell is hush, which lacks functions. You can simulate functions with eval. I'll assume you have test; if you don't, detecting directories is possible but painful.
command='grep -H PATTERN'
traverse='
for x in "$d"/* "$d"/.[!.]* "$d"/..?*; do
if test -f "$x"; then
'"$command"' "$x"
elif test -d "$x"; then
d="$x"
eval "$traverse"
fi
done
'
d=/some/dir
eval "$traverse"