3

How can I find a file containing a certain string on a BusyBox 1.0, if grep -r does not work?

6

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"
  • Actually, my BusyBox find does accept -exec ... +, though it treats it the same as -exec ... \;. Not sure if this is a configurable option. Not very useful, but it does make some scripts written for other systems a bit more portable. – dubiousjim Jan 14 '13 at 2:46

Your Answer

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