34

Is there any way to use pipe within an -exec in find? I don't want grep to go through whole file, but only through first line of each file.

find /path/to/dir -type f -print -exec grep yourstring {} \;

I tried to put the pipelines there with "cat" and "head -1", but it didn't work very well. I tried to use parenthesis somehow, but I didn't manage to work out how exactly to put them there. I would be very thankful for your help. I know how to work it out other way, without using the find, but we tried to do it in school with the usage of find and pipeline, but couldn`t manage how to.

find /path/to/dir -type f -print -exec cat {} | head -1 | grep yourstring \;

This is somehow how we tried to do it, but could't manage the parenthesis and wheter it is even possible. I tried to look through net, but couldn' t find any answers.

beranpa8
  • 435
  • 1
  • 5
  • 11
  • I'm voting to close this question as off-topic because this belongs to unix.stackexchange.com and has an answer there at https://unix.stackexchange.com/questions/42407/pipe-find-into-grep-v – koppor Jan 31 '18 at 08:39
  • Another answer (for grepping) is there http://serverfault.com/questions/9822/recursive-text-search-with-grep-and-file-patterns – koppor Jan 31 '18 at 08:44
  • Possible duplicate of [How do I use a pipe in the exec parameter for a find command?](https://stackoverflow.com/questions/62044/how-do-i-use-a-pipe-in-the-exec-parameter-for-a-find-command) – Fabio says Reinstate Monica Nov 23 '18 at 16:27

2 Answers2

57

In order to be able to use a pipe, you need to execute a shell command, i.e. the command with the pipeline has to be a single command for -exec.

find /path/to/dir -type f -print -exec sh -c "cat {} | head -1 | grep yourstring" \;

Note that the above is a Useless Use of Cat, that could be written as:

find /path/to/dir -type f -print -exec sh -c "head -1 {} | grep yourstring" \;

Another way to achieve what you want would be to say:

find /path/to/dir -type f -print -exec awk 'NR==1 && /yourstring/' {} \;
devnull
  • 118,548
  • 33
  • 236
  • 227
3

This does not directly answer your question, but if you want to do some complex operations you might be better off scripting:

for file in $(find /path/to/dir -type f); do echo ${file}; cat $file | head -1 | grep yourstring; done

crutux
  • 97
  • 1
  • 1
  • 8
  • A loop through file names with white spaces in "find" will give some problems. Here you have a post with a good answer: https://stackoverflow.com/questions/9612090/how-to-loop-through-file-names-returned-by-find?answertab=votes#tab-top – lamanux Jul 24 '18 at 07:39
  • Yes, this will not work for files that contain spaces, it will also split those filenames up. I like this approach (using a for loop), since it's clearer to read. But this has some issues. lamanux's link is good – Patrick Mar 22 '22 at 03:57