Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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

share|improve this question

migrated from stackoverflow.com Jan 27 '12 at 0:09

This question came from our site for professional and enthusiast programmers.

add comment

1 Answer 1

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"
share|improve this answer
    
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
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.