Why does `find` in Linux skip expected results when `-o` is used?
Why in Linux (Debian 8)
touch 1.cpp 1.h
find . -name "*.cpp" -o -name "*.h" -exec echo {} ;
outputs only 1.h
while
find . -name "*.cpp" -o -name "*.h"
outputs both? Is it a bug or feature?
linux find
add a comment |
Why in Linux (Debian 8)
touch 1.cpp 1.h
find . -name "*.cpp" -o -name "*.h" -exec echo {} ;
outputs only 1.h
while
find . -name "*.cpp" -o -name "*.h"
outputs both? Is it a bug or feature?
linux find
add a comment |
Why in Linux (Debian 8)
touch 1.cpp 1.h
find . -name "*.cpp" -o -name "*.h" -exec echo {} ;
outputs only 1.h
while
find . -name "*.cpp" -o -name "*.h"
outputs both? Is it a bug or feature?
linux find
Why in Linux (Debian 8)
touch 1.cpp 1.h
find . -name "*.cpp" -o -name "*.h" -exec echo {} ;
outputs only 1.h
while
find . -name "*.cpp" -o -name "*.h"
outputs both? Is it a bug or feature?
linux find
linux find
edited Feb 17 at 19:52
Kamil Maciorowski
24.5k155277
24.5k155277
asked Sep 2 '15 at 10:21
mastan
332
332
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
I think once you used -or
operator, then you've to keep it consistent in order to avoid ambiguous order of logical operations when you have multiple conditions connected using logical OR.
It seems the -exec
part is grouped together with the second -name "*.h"
.
So in order to make it work correctly, you've to add the brackets as below:
find . '(' -name '*.cpp' -o -name '*.h' ')' -exec echo {} ';'
Remember: The parentheses must be quoted or escaped with a backslash to prevent them from being interpreted as special shell characters.
Alternatively combine few extensions into one by using -regex
:
find . ! -regex ".*.(cpp|h)" -exec echo {} ;
add a comment |
Try to surround your search criteria with brackets as such:
find . ( -name "*.cpp" -o -name "*.h" ) -exec echo {} ;
add a comment |
Neither. It's the syntax of the options that is "wrong". find
evalutates sequencially. Hence, it evaluates the first expression (-name "*.cpp"
) then encounters a -o
flag. If the first expression is true, find
will not continue evaluating the second one (-name "*.h" -exec echo {} ;
), instead does nothing. You see, the whole part after -o
is one expression. Therefore, this is only executed for files that match the second expression. That's why you see only the 1.h
file, which passes only the second expression. See the find manpage:
expr1 -o expr2
Or; expr2 is not evaluated if expr1 is true.
Why is this useful? Consider the following:
find /path -exec test_file_for_something {} -print ; -o -name "xyz" -exec ls -l {} ;
In this find statement the file is given to test_file_for_something
as a parameter. Now, depending on that commands return code the first expression is true (then -print
is executed and it ends there) or false (then the second expression after the -o
flag is evaluated). And if that one is true (the name is xyz
), then -exec
is executed.
For your problem you can instead use this to group the elements together as one expression:
find . ( -name "*.cpp" -o -name "*.h" ) -exec echo {} ;
add a comment |
That is the way find works with it's operators.
See http://linux.die.net/man/1/find section OPERATORS
OPERATORS
Listed in order of decreasing precedence: ( expr ) Force precedence.
Since parentheses are special to the shell, you will normally need to
quote them. Many of the examples in this manual page use backslashes
for this purpose: '(...)' instead of '(...)'. ! expr True if expr is
false. This character will also usually need protection from
interpretation by the shell.
-not expr Same as ! expr, but not POSIX compliant. expr1 expr2 Two expressions in a row are taken to be joined with an implied "and";
expr2 is not evaluated if expr1 is false. expr1 -a expr2 Same as expr1
expr2. expr1 -and expr2 Same as expr1 expr2, but not POSIX compliant.
expr1 -o expr2 Or; expr2 is not evaluated if expr1 is true. expr1 -or
expr2 Same as expr1 -o expr2, but not POSIX compliant. expr1 , expr2
List; both expr1 and expr2 are always evaluated. The value of expr1 is
discarded; the value of the list is the value of expr2. The comma
operator can be useful for searching for several different types of
thing, but traversing the filesystem hierarchy only once. The -fprintf
action can be used to list the various matched items into several
different output files.
This should give you the result you want:
find . ( -name '*.cpp' -o -name '*.h' ) -exec echo {} ;
Your command is doing this (command won't work, just to show you the logic):
find . -name '*.cpp' (-o -name '*.h' -exec echo {} ;)
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "3"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsuperuser.com%2fquestions%2f966227%2fwhy-does-find-in-linux-skip-expected-results-when-o-is-used%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
I think once you used -or
operator, then you've to keep it consistent in order to avoid ambiguous order of logical operations when you have multiple conditions connected using logical OR.
It seems the -exec
part is grouped together with the second -name "*.h"
.
So in order to make it work correctly, you've to add the brackets as below:
find . '(' -name '*.cpp' -o -name '*.h' ')' -exec echo {} ';'
Remember: The parentheses must be quoted or escaped with a backslash to prevent them from being interpreted as special shell characters.
Alternatively combine few extensions into one by using -regex
:
find . ! -regex ".*.(cpp|h)" -exec echo {} ;
add a comment |
I think once you used -or
operator, then you've to keep it consistent in order to avoid ambiguous order of logical operations when you have multiple conditions connected using logical OR.
It seems the -exec
part is grouped together with the second -name "*.h"
.
So in order to make it work correctly, you've to add the brackets as below:
find . '(' -name '*.cpp' -o -name '*.h' ')' -exec echo {} ';'
Remember: The parentheses must be quoted or escaped with a backslash to prevent them from being interpreted as special shell characters.
Alternatively combine few extensions into one by using -regex
:
find . ! -regex ".*.(cpp|h)" -exec echo {} ;
add a comment |
I think once you used -or
operator, then you've to keep it consistent in order to avoid ambiguous order of logical operations when you have multiple conditions connected using logical OR.
It seems the -exec
part is grouped together with the second -name "*.h"
.
So in order to make it work correctly, you've to add the brackets as below:
find . '(' -name '*.cpp' -o -name '*.h' ')' -exec echo {} ';'
Remember: The parentheses must be quoted or escaped with a backslash to prevent them from being interpreted as special shell characters.
Alternatively combine few extensions into one by using -regex
:
find . ! -regex ".*.(cpp|h)" -exec echo {} ;
I think once you used -or
operator, then you've to keep it consistent in order to avoid ambiguous order of logical operations when you have multiple conditions connected using logical OR.
It seems the -exec
part is grouped together with the second -name "*.h"
.
So in order to make it work correctly, you've to add the brackets as below:
find . '(' -name '*.cpp' -o -name '*.h' ')' -exec echo {} ';'
Remember: The parentheses must be quoted or escaped with a backslash to prevent them from being interpreted as special shell characters.
Alternatively combine few extensions into one by using -regex
:
find . ! -regex ".*.(cpp|h)" -exec echo {} ;
edited Sep 26 '15 at 21:08
answered Sep 2 '15 at 10:41
kenorb
10.7k1577111
10.7k1577111
add a comment |
add a comment |
Try to surround your search criteria with brackets as such:
find . ( -name "*.cpp" -o -name "*.h" ) -exec echo {} ;
add a comment |
Try to surround your search criteria with brackets as such:
find . ( -name "*.cpp" -o -name "*.h" ) -exec echo {} ;
add a comment |
Try to surround your search criteria with brackets as such:
find . ( -name "*.cpp" -o -name "*.h" ) -exec echo {} ;
Try to surround your search criteria with brackets as such:
find . ( -name "*.cpp" -o -name "*.h" ) -exec echo {} ;
answered Sep 2 '15 at 10:41
Art Gertner
5,849113363
5,849113363
add a comment |
add a comment |
Neither. It's the syntax of the options that is "wrong". find
evalutates sequencially. Hence, it evaluates the first expression (-name "*.cpp"
) then encounters a -o
flag. If the first expression is true, find
will not continue evaluating the second one (-name "*.h" -exec echo {} ;
), instead does nothing. You see, the whole part after -o
is one expression. Therefore, this is only executed for files that match the second expression. That's why you see only the 1.h
file, which passes only the second expression. See the find manpage:
expr1 -o expr2
Or; expr2 is not evaluated if expr1 is true.
Why is this useful? Consider the following:
find /path -exec test_file_for_something {} -print ; -o -name "xyz" -exec ls -l {} ;
In this find statement the file is given to test_file_for_something
as a parameter. Now, depending on that commands return code the first expression is true (then -print
is executed and it ends there) or false (then the second expression after the -o
flag is evaluated). And if that one is true (the name is xyz
), then -exec
is executed.
For your problem you can instead use this to group the elements together as one expression:
find . ( -name "*.cpp" -o -name "*.h" ) -exec echo {} ;
add a comment |
Neither. It's the syntax of the options that is "wrong". find
evalutates sequencially. Hence, it evaluates the first expression (-name "*.cpp"
) then encounters a -o
flag. If the first expression is true, find
will not continue evaluating the second one (-name "*.h" -exec echo {} ;
), instead does nothing. You see, the whole part after -o
is one expression. Therefore, this is only executed for files that match the second expression. That's why you see only the 1.h
file, which passes only the second expression. See the find manpage:
expr1 -o expr2
Or; expr2 is not evaluated if expr1 is true.
Why is this useful? Consider the following:
find /path -exec test_file_for_something {} -print ; -o -name "xyz" -exec ls -l {} ;
In this find statement the file is given to test_file_for_something
as a parameter. Now, depending on that commands return code the first expression is true (then -print
is executed and it ends there) or false (then the second expression after the -o
flag is evaluated). And if that one is true (the name is xyz
), then -exec
is executed.
For your problem you can instead use this to group the elements together as one expression:
find . ( -name "*.cpp" -o -name "*.h" ) -exec echo {} ;
add a comment |
Neither. It's the syntax of the options that is "wrong". find
evalutates sequencially. Hence, it evaluates the first expression (-name "*.cpp"
) then encounters a -o
flag. If the first expression is true, find
will not continue evaluating the second one (-name "*.h" -exec echo {} ;
), instead does nothing. You see, the whole part after -o
is one expression. Therefore, this is only executed for files that match the second expression. That's why you see only the 1.h
file, which passes only the second expression. See the find manpage:
expr1 -o expr2
Or; expr2 is not evaluated if expr1 is true.
Why is this useful? Consider the following:
find /path -exec test_file_for_something {} -print ; -o -name "xyz" -exec ls -l {} ;
In this find statement the file is given to test_file_for_something
as a parameter. Now, depending on that commands return code the first expression is true (then -print
is executed and it ends there) or false (then the second expression after the -o
flag is evaluated). And if that one is true (the name is xyz
), then -exec
is executed.
For your problem you can instead use this to group the elements together as one expression:
find . ( -name "*.cpp" -o -name "*.h" ) -exec echo {} ;
Neither. It's the syntax of the options that is "wrong". find
evalutates sequencially. Hence, it evaluates the first expression (-name "*.cpp"
) then encounters a -o
flag. If the first expression is true, find
will not continue evaluating the second one (-name "*.h" -exec echo {} ;
), instead does nothing. You see, the whole part after -o
is one expression. Therefore, this is only executed for files that match the second expression. That's why you see only the 1.h
file, which passes only the second expression. See the find manpage:
expr1 -o expr2
Or; expr2 is not evaluated if expr1 is true.
Why is this useful? Consider the following:
find /path -exec test_file_for_something {} -print ; -o -name "xyz" -exec ls -l {} ;
In this find statement the file is given to test_file_for_something
as a parameter. Now, depending on that commands return code the first expression is true (then -print
is executed and it ends there) or false (then the second expression after the -o
flag is evaluated). And if that one is true (the name is xyz
), then -exec
is executed.
For your problem you can instead use this to group the elements together as one expression:
find . ( -name "*.cpp" -o -name "*.h" ) -exec echo {} ;
answered Sep 2 '15 at 11:03
chaos
3,40821026
3,40821026
add a comment |
add a comment |
That is the way find works with it's operators.
See http://linux.die.net/man/1/find section OPERATORS
OPERATORS
Listed in order of decreasing precedence: ( expr ) Force precedence.
Since parentheses are special to the shell, you will normally need to
quote them. Many of the examples in this manual page use backslashes
for this purpose: '(...)' instead of '(...)'. ! expr True if expr is
false. This character will also usually need protection from
interpretation by the shell.
-not expr Same as ! expr, but not POSIX compliant. expr1 expr2 Two expressions in a row are taken to be joined with an implied "and";
expr2 is not evaluated if expr1 is false. expr1 -a expr2 Same as expr1
expr2. expr1 -and expr2 Same as expr1 expr2, but not POSIX compliant.
expr1 -o expr2 Or; expr2 is not evaluated if expr1 is true. expr1 -or
expr2 Same as expr1 -o expr2, but not POSIX compliant. expr1 , expr2
List; both expr1 and expr2 are always evaluated. The value of expr1 is
discarded; the value of the list is the value of expr2. The comma
operator can be useful for searching for several different types of
thing, but traversing the filesystem hierarchy only once. The -fprintf
action can be used to list the various matched items into several
different output files.
This should give you the result you want:
find . ( -name '*.cpp' -o -name '*.h' ) -exec echo {} ;
Your command is doing this (command won't work, just to show you the logic):
find . -name '*.cpp' (-o -name '*.h' -exec echo {} ;)
add a comment |
That is the way find works with it's operators.
See http://linux.die.net/man/1/find section OPERATORS
OPERATORS
Listed in order of decreasing precedence: ( expr ) Force precedence.
Since parentheses are special to the shell, you will normally need to
quote them. Many of the examples in this manual page use backslashes
for this purpose: '(...)' instead of '(...)'. ! expr True if expr is
false. This character will also usually need protection from
interpretation by the shell.
-not expr Same as ! expr, but not POSIX compliant. expr1 expr2 Two expressions in a row are taken to be joined with an implied "and";
expr2 is not evaluated if expr1 is false. expr1 -a expr2 Same as expr1
expr2. expr1 -and expr2 Same as expr1 expr2, but not POSIX compliant.
expr1 -o expr2 Or; expr2 is not evaluated if expr1 is true. expr1 -or
expr2 Same as expr1 -o expr2, but not POSIX compliant. expr1 , expr2
List; both expr1 and expr2 are always evaluated. The value of expr1 is
discarded; the value of the list is the value of expr2. The comma
operator can be useful for searching for several different types of
thing, but traversing the filesystem hierarchy only once. The -fprintf
action can be used to list the various matched items into several
different output files.
This should give you the result you want:
find . ( -name '*.cpp' -o -name '*.h' ) -exec echo {} ;
Your command is doing this (command won't work, just to show you the logic):
find . -name '*.cpp' (-o -name '*.h' -exec echo {} ;)
add a comment |
That is the way find works with it's operators.
See http://linux.die.net/man/1/find section OPERATORS
OPERATORS
Listed in order of decreasing precedence: ( expr ) Force precedence.
Since parentheses are special to the shell, you will normally need to
quote them. Many of the examples in this manual page use backslashes
for this purpose: '(...)' instead of '(...)'. ! expr True if expr is
false. This character will also usually need protection from
interpretation by the shell.
-not expr Same as ! expr, but not POSIX compliant. expr1 expr2 Two expressions in a row are taken to be joined with an implied "and";
expr2 is not evaluated if expr1 is false. expr1 -a expr2 Same as expr1
expr2. expr1 -and expr2 Same as expr1 expr2, but not POSIX compliant.
expr1 -o expr2 Or; expr2 is not evaluated if expr1 is true. expr1 -or
expr2 Same as expr1 -o expr2, but not POSIX compliant. expr1 , expr2
List; both expr1 and expr2 are always evaluated. The value of expr1 is
discarded; the value of the list is the value of expr2. The comma
operator can be useful for searching for several different types of
thing, but traversing the filesystem hierarchy only once. The -fprintf
action can be used to list the various matched items into several
different output files.
This should give you the result you want:
find . ( -name '*.cpp' -o -name '*.h' ) -exec echo {} ;
Your command is doing this (command won't work, just to show you the logic):
find . -name '*.cpp' (-o -name '*.h' -exec echo {} ;)
That is the way find works with it's operators.
See http://linux.die.net/man/1/find section OPERATORS
OPERATORS
Listed in order of decreasing precedence: ( expr ) Force precedence.
Since parentheses are special to the shell, you will normally need to
quote them. Many of the examples in this manual page use backslashes
for this purpose: '(...)' instead of '(...)'. ! expr True if expr is
false. This character will also usually need protection from
interpretation by the shell.
-not expr Same as ! expr, but not POSIX compliant. expr1 expr2 Two expressions in a row are taken to be joined with an implied "and";
expr2 is not evaluated if expr1 is false. expr1 -a expr2 Same as expr1
expr2. expr1 -and expr2 Same as expr1 expr2, but not POSIX compliant.
expr1 -o expr2 Or; expr2 is not evaluated if expr1 is true. expr1 -or
expr2 Same as expr1 -o expr2, but not POSIX compliant. expr1 , expr2
List; both expr1 and expr2 are always evaluated. The value of expr1 is
discarded; the value of the list is the value of expr2. The comma
operator can be useful for searching for several different types of
thing, but traversing the filesystem hierarchy only once. The -fprintf
action can be used to list the various matched items into several
different output files.
This should give you the result you want:
find . ( -name '*.cpp' -o -name '*.h' ) -exec echo {} ;
Your command is doing this (command won't work, just to show you the logic):
find . -name '*.cpp' (-o -name '*.h' -exec echo {} ;)
answered Sep 2 '15 at 10:43
HoD
1,640415
1,640415
add a comment |
add a comment |
Thanks for contributing an answer to Super User!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsuperuser.com%2fquestions%2f966227%2fwhy-does-find-in-linux-skip-expected-results-when-o-is-used%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown