4

I need to find which files (they can have space in the filename) of a directory contains a string using only sh and system's commands (Perl is not an option).

For a few files, this command works fine:

# grep -l word *
file 1
file1

But if I have 270k file, I obtain the following error:

#  grep -l word *
sh: /usr/bin/grep: The parameter list is too long.

In HP-UX, the xargs command doesn't have the -0 option, so I can't use this:

# find . -print0 |xargs -0 grep -l
xargs: unknown option: -0

Do you know which command I can use?

5

You could use a variant of your find command like this:

find . -type f -exec grep -l word {} \; 
  • You forgot to write the word to search, so this does not answer the problem, so this should not be the best answer unless Mat correct it. @Gilles answer is better and more complete imho. – Gabriel Hautclocq Aug 31 '17 at 15:32
  • Well spotted. Feel free to suggest edits if you spot typoes like that. – Mat Aug 31 '17 at 15:36
  • That's better now :-) Still less complete than Gilles answer but works for everyone. – Gabriel Hautclocq Aug 31 '17 at 15:50
4

If your version of HP-UX is recent enough, you can call find with the -exec … + action. This action does the same job as xargs (call a command on multiple matching files at once, without overflowing the command line length limit), but in a reliable way for any file name.

find . -type f -exec grep -l word {} +

If your version of HP-UX is too old, you might have only -exec … \; and not -exec … +. The ; version calls the command on one file at a time, which is a bit slower.

find . -type f -exec grep -l word {} \;

If your file names don't contain \"' or whitespace, then you can use xargs without the -0 option.

find . -type f -print | xargs grep -l word
0

For a close POSIX equivalent to grep -l word ./* that splits the list of files as need to avoid the execve() limit on the size of the arguments, you could do:

find -L . ! -name . -prune ! -name '.*' -type f -exec \
  grep -l word /dev/null {} +
  • ! -name . -prune is to not recurse into sub-directories
  • -L in combination with -type f is to search in regular files only (after symlink resolution) (a bonus compared to the grep ... ./* approach which would look inside any type of file)
  • ! -name '.*' to exclude hidden files as ./* does
  • /dev/null to make sure the file name is always printed (another bonus).

A notable difference is that the list of files won't be sorted.

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.