Bash – How to run “find -exec
Related Solutions
As for the find
command, you can also just add more -exec
commands in a row:
find . -name "*" -exec chgrp -v new_group '{}' \; -exec chmod -v 770 '{}' \;
Note that this command is, in its result, equivalent of using
chgrp -v new_group file && chmod -v 770 file
on each file.
All the find
's parameters such as -name
, -exec
, -size
and so on, are actually tests: find
will continue to run them one by one as long as the entire chain so far has evaluated to true. So each consecutive -exec
command is executed only if the previous ones returned true (i.e. 0
exit status of the commands). But find
also understands logic operators such as or (-o
) and not (!
). Therefore, to use a chain of -exec
tests regardless of the previous results, one would need to use something like this:
find . -name "*" \( -exec chgrp -v new_group {} \; -o -true \) -exec chmod -v 770 {} \;
-exec
is a predicate that runs a command (not a shell) and evaluates to true or false based on the outcome of the command (zero or non-zero exit status).
So:
find . -iname '*.csv' -exec grep foo {} \; -print
would print the file path if grep
finds foo in the file. Instead of -print
you can use another -exec
predicate or any other predicate
find . -iname '*.csv' -exec grep foo {} \; -exec echo {} \;
See also the !
and -o
find operators for negation and or.
Alternatively, you can start a shell as:
find . -iname '*.csv' -exec sh -c '
grep foo "$1" && echo "$1"' sh {} \;
Or to avoid having to start a shell for every file:
find . -iname '*.csv' -exec sh -c '
for i do
grep foo "$i" && echo "$i"
done' sh {} +
Related Solutions
As for the find
command, you can also just add more -exec
commands in a row:
find . -name "*" -exec chgrp -v new_group '{}' \; -exec chmod -v 770 '{}' \;
Note that this command is, in its result, equivalent of using
chgrp -v new_group file && chmod -v 770 file
on each file.
All the find
's parameters such as -name
, -exec
, -size
and so on, are actually tests: find
will continue to run them one by one as long as the entire chain so far has evaluated to true. So each consecutive -exec
command is executed only if the previous ones returned true (i.e. 0
exit status of the commands). But find
also understands logic operators such as or (-o
) and not (!
). Therefore, to use a chain of -exec
tests regardless of the previous results, one would need to use something like this:
find . -name "*" \( -exec chgrp -v new_group {} \; -o -true \) -exec chmod -v 770 {} \;
-exec
is a predicate that runs a command (not a shell) and evaluates to true or false based on the outcome of the command (zero or non-zero exit status).
So:
find . -iname '*.csv' -exec grep foo {} \; -print
would print the file path if grep
finds foo in the file. Instead of -print
you can use another -exec
predicate or any other predicate
find . -iname '*.csv' -exec grep foo {} \; -exec echo {} \;
See also the !
and -o
find operators for negation and or.
Alternatively, you can start a shell as:
find . -iname '*.csv' -exec sh -c '
grep foo "$1" && echo "$1"' sh {} \;
Or to avoid having to start a shell for every file:
find . -iname '*.csv' -exec sh -c '
for i do
grep foo "$i" && echo "$i"
done' sh {} +
Best Answer
You are missing the space between
{}
and;
: