1

I need to reduce the following into a single find statements.

$ find . -print | grep dir
$ find . -print | grep ch

The only tip was given to me was to read man page to manage to do this. I read through it and had the following conclusion, can someone tell me if I am making the right thinking or if they can direct me to a helpful site where I can understand reducing pipe lines more.

Attempts to do this in a single line:

$ find . -print | grep dir && grep ch
$ find . -print | grep dir , grep ch

or making use of printf.

Does the above make sense or will it give me: not found?

Timur Shtatland
  • 12,024
  • 2
  • 30
  • 47
xor
  • 39
  • 7

2 Answers2

4

Use find with -name options, connected by -o (= logical or), like so:

find . \( -name '*dir*' -o -name '*ch*' \)
Timur Shtatland
  • 12,024
  • 2
  • 30
  • 47
  • ok so if my top folder is named groc, my sub folder is fruits and i want terminal to find the folders apple and banana inside the folder fruits for example. Is this the right way to write it? find . \( -groc'*dir*' -o -fruits'*ch*' \) ?? or am I understanding shell wrongly. thank you for patience. I am very new to this and trying to understand and thanks for help – xor Dec 29 '20 at 21:44
  • You need `find groc/fruits -type d \( -name apple -o -name banana \)`. You would get better help (from more people) if you ask this as a separate question, instead of as a comment. – Timur Shtatland Dec 29 '20 at 21:53
  • makes more sense than my thinking thank you ok thkx for suggestion. – xor Dec 29 '20 at 21:58
  • Parenthesis not needed here. So this will work too: `find . -name '*dir*' -o -name '*ch*'` – Wiimm Dec 30 '20 at 00:26
0

Both lines use this expression as their input:

find . -print

So what you will want to do is pipe the result of evaluating that expression to the two grep calls.

find . -print | (grep dir; grep ch)

Note: You'll want to be careful of doing something like what you had previously proposed as a solution, because of short circuit evaluation. That is-

find . -print | expr1 && expr 2

This only evaluates both if expr1 returns True, positive or non null value (because both operands need to be true for and to return true). In your case, you want both grep dir and grep ch to evaluate every time, regardless of whether the first grep found anything.

find . -print | expr1 || expr 2

This does not evaluate expr2 if expr1 returns True, positive or non null value (Because or requires only one operand to be true in order to return true)

Rather than && or ||, use semi colon.

expr1; expr2

echo hello; echo world

That is a clean way to group two expressions without one logically dependent on the output of the other.

breadman0
  • 163
  • 1
  • 4
  • 14
  • I agree with @johnathan leffler. His is probably the better. right solution, but the concepts in my answer was a breakthrough for me when I was taking bash class – breadman0 Dec 29 '20 at 21:18
  • When I used the ; only expression1 was outputted for some reason will tell you if it works when I try it again – xor Dec 29 '20 at 21:26
  • This just doesn't work. E.g. `find . -print | (grep dir; grep ch)` will pipe the output from the `find` command to the first `grep`, which will read until there's no input left. Then the second `grep` command will run with empty input and consequently print nothing at all. Also, `&&` or `||` won't help here. – Elmar Zander Mar 28 '23 at 10:39