0

I tried to find all the lines containing word heaq in *.md file

$  for i in $(find . -regex ".*md$"); do grep -i "heaq"; done
#pending
#pending

However, it constantly pending there.

What's the problem with my code?

Kusalananda
  • 333,661
Wizard
  • 2,503
  • you're not passing any file argument to grep, so grep will expect its input from stdin; enter a line of the form 'yeah heaq' when it's "pending" and grep will kindly print it back. –  Nov 05 '18 at 01:23

2 Answers2

4

It is the grep that is "pending". When grep is run without a filename to read from, it will read standard input. If you don't provide any data on standard input, it will appear to "hang".

You are also looping over the output of find. This is inelegant (the loop won't run until all pathnames has been found by find) and dangerous (the pathnames will be split on whitespaces and the shell will perform filename globbing on them).

Instead, if you want to run grep on all files with a particular filename suffix:

find . -type f -name '*.md' -exec grep -iF 'heaq' {} +

I've changed the -regex thing to a standard -name test with a pattern that matches only filenames with a .md filename suffix. I've also added -type f as it only makes sense to run grep on regular files (you may possibly want to change -type f to ! -type d to run it on any non-directory instead).

The grep is executed through -exec in batches on the found pathnames. I'm using -F with grep as we are matching a string, not a regular expression. You may want to add -w if you want to match a word rather than any substring.

Related:

Kusalananda
  • 333,661
3

you need to pass the file name to grep

so like

$ for i in $(find . -regex ".*md$"); do grep -i "heaq" $i; done

you can also use

% grep -i -n "heaq" $(find . -regex ".*md$")

-n makes grep prints out matching line numbers

Rio6
  • 372
  • 2
    +1 for the diagnosis; however looping over find output in this manner is going to be fragile - better to use something like find . -regex ".*md$" -exec grep -i "heaq" {} ';' (or find . -regex ".*md$" -exec grep -i "heaq" {} + if supported). Also worth pointing out that -regex is overkill here - a simple -name "*.md" glob match should be sufficient – steeldriver Nov 05 '18 at 01:33
  • @steeldriver Any find implementation that has the non-standard -regex is bound to have the standard -exec ... {} +. – Kusalananda Nov 05 '18 at 06:54