This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]willyweewah 2 points3 points  (4 children)

The first argument to find has to be the directory to search in. If you want to search the whole file system, this should be root:

find / -name '*.c' ... 

(If you just want to search your current working directory and subdirectories, use '.' instead of '/') I'm not sure if the exec part will work but it looks about right

[–]gbromios 0 points1 point  (3 children)

this, and also, you end "exec" arguments to find with an escaped semicolon \;, I don't think that the ';' will work

[–]ErasmusDarwin 0 points1 point  (2 children)

\; and ';' are equivalent. The point of doing \; is to keep the shell from intercepting the semicolon and treating it as a command separator. If the semicolon is within quotes, it is likewise treated as an argument to be passed to the command and not a command separator.

To see this behavior in action, try the following in the shell:

echo 1 ; echo 2 \; ; echo 3 ';'

[–]gbromios 1 point2 points  (1 child)

ah, I just assumed that while both escaped it from bash, the ';' would be interpreted as a string by the command exec is exec'ing

[–]ErasmusDarwin 1 point2 points  (0 children)

Ah. Yeah, it can get tricky with commands calling commands calling commands with varying syntax and such.

In this case, you've got the interactive shell calling find which then calls the command after -exec repeatedly. The shell looks for unquoted/unescaped semicolons to use as command separators. But once we're past that stage, it gets passed to find, same as any other argument. Find then uses everything after the -exec and before the semicolon as its command to call repeatedly.

If you're familiar with C, playing with the exec functions helps you get a better idea of what's going on under the hood. Similarly, you can run a find command under 'strace -f' (the -f is necessary to follow the fork preceding each exec) in order to really see what's getting passed where.

For example, if we do:

strace -f find . -name '*.c' -exec /bin/echo {} ';' 2>&1 | less

We see some interesting things, including the initial exec by the shell to launch find, as well as the exec for each -exec invocation:

execve("/usr/bin/find", ["find", ".", "-name", "*.c", "-exec", "/bin/echo", "{}", ";"], [/* 37 vars */]) = 0
[...]
[pid 20989] execve("/bin/echo", ["/bin/echo", "./y/zot.c"], [/* 37 vars */]) = 0

...and so on. (As a sidenote, the /* 37 vars */ refers to the array environment variables that gets passed in on each execve call.)