Shell notation: find . -type f -exec file '{}' \; [duplicate] - linux

This question already has answers here:
Why are the backslash and semicolon required with the find command's -exec option?
(2 answers)
Closed 9 years ago.
This is a relatively simple command, so if a duplicate exists and someone could refer me, I'm sorry and I'll delete/close this question.
Man page for find
find . -type f -exec file '{}' \;
Runs 'file' on every file in or below the current directory. Notice that the braces are enclosed in single quote marks to protect them from interpretation
as shell script punctuation. The semicolon is similarly protected by the use of a backslash, though ';' could have been used in that case also.
I do not understand the notation \;. What in the world is that?

In the find command, the action -exec is followed by a command and that command's arguments. Because there can be any number of arguments, find needs some way of knowing when it ends. The semicolon is what tells find that it has reached the end of the command's arguments.
Left to their own devices, most shells would eat the semicolon. We want that semicolon to be passed to the find command. Therefore, we escape it with a backslash. This tells the shell to treat the semicolon as just one of the arguments to the find command.
MORE: Why not, one may ask, just assume that the exec command's argument just go to the end of the line? Why do we need to signal an end to the exec command's arguments at all? The reason is that find has advanced features. Just for example, consider:
find . -name '*.pdf' -exec echo Yes, we have a pdf: {} \; -o -exec echo No, not a pdf: {} \;

Related

What does this strange construction "{} \;" means?

Why do we use this strange construction {} \; in linux terminal for exec command?
For example,
find . -type f -name *.jpeg -exec rm {} \;
From the man page of find (emphasis mine):
find . -type f -exec file '{}' \;
Runs `file' on every file in or below the current directory. Notice that the braces are enclosed in single quote marks to protect them from interpretation as shell script punctuation. The semicolon is similarly protected by the use of a backslash, though single quotes could have been used in that case also.
Looking for info I found this post in AskUbuntu which I think is family from StackOverflow where an User ask the same as you.
Link
Hope It is useful.

Use of "{}" and "\;" in sed command [duplicate]

This question already has answers here:
Unix find command, what are the {} and \; for?
(5 answers)
Closed 6 years ago.
I've been googling this, but although I see people using them, I see no explanation for it. I've also tried "find and sed" searches, but again no explanation on these. The sed man and other sed guides out there also don't include it.
Now, I'm using the find command to find several files and then using sed to replace strings whithin the files. I believe that these "{}" and "\;" at the end of the sed are what allows sed to take each file name from find and search through its text. But I'd rather not guess and know for sure what they are and why they're there. Here's my current command:
output=$(find . -type f -name '*.h' -o -name '*.C' -o -name '*.cpp' -o -name "*.cc" -exec sed -n -i "s/ARG2/ARG3/g" {} \;)
I'm also concerned that the ";" at the end may not be necessary since I'm wrapping it also and throwing it into a variable. Could someone clarify what those curlies and backslash are doing and whether I need them?
EDIT: It turns out that they're properties of find -exec, not sed. So I've been looking in the wrong place. Thanks!
find has two versions of the -exec action:
-exec ... {} +
...runs the command ..., with as many filenames from the results as possible added at the end.
-exec ... {} ';'
...runs the command ... once per file found, with the filename substituted in place of the {} sigil; it's not mandatory that the sigil be at the end of the line in this usage.
Thus, either a + or ; needs to be passed as a literal argument to find for it to accept the action as valid.

Why are the backslash and semicolon required with the find command's -exec option?

I have begun to combine different commands in the linux terminal. I am wondering why the backslash and semicolon are required for a command such as:
find ./ -name 'blabla' -exec cp {} ./test \;
when a simple cp command is simply:
cp randomfile ./test
without the \;
Are they to clearly indicate the end of a command, or is it simply required in the documentation? What is the underlying principle?
The backslash before the semicolon is used, because ; is one of list operators (or &&, ||) for separating shell commands. In example:
command1; command2
The find utility is using ; or + to terminate the shell commands invoked by -exec.
So to avoid special shell characters from interpretation, they need to be escaped with a backslash to remove any special meaning for the next character read and for line continuation.
Therefore the following example syntax is allowed for find command:
find . -exec echo {} \;
find . -exec echo {} ';'
find . -exec echo {} ";"
find . -exec echo {} \+
find . -exec echo {} +
See also:
Using semicolon (;) vs plus (+) with exec in find
Simple unix command, what is the {} and \; for
from "man find":
All following
arguments to find are taken to be arguments to the command until
an argument consisting of ';' is encountered.
find needs to know when the arguments of exec are terminated. It is natural to terminate a shell command with ; because also the shell uses this character. For the very same reason such a character must be escaped when inserted through the shell.

renaming with find

I managed to find several files with the find command.
the files are of the type file_sakfksanf.txt, file_afsjnanfs.pdf, file_afsnjnjans.cpp,
now I want to rename them with the rename and -exec command to
mywish_sakfksanf.txt, mywish_afsjnanfs.pdf, mywish_afsnjnjans.cpp
that only the first prefix is changed. I am trying for some time, so don't blame me for being stupid.
If you read through the -exec section of the man pages for find you will come across the {} string that allows you to use the matches as arguments within -exec. This will allow you to use rename on your find matches in the following way:
find . -name 'file_*' -exec rename 's/file_/mywish_/' {} \;
From the manual:
-exec command ;
Execute command; true if 0 status is returned. All following
arguments to find are taken to be arguments to the command until an
argument consisting of ;' is encountered. The string{}' is replaced
by the current file name being processed everywhere it occurs in the
arguments to the command, not just in arguments where it is alone, as
in some versions of find. Both of these constructions might need to
be escaped (with a `\') or quoted to protect them from expansion by
the shell. See the EXAMPLES section for examples of the use of the
-exec option. The specified command is run once for each matched file. The command is executed in the starting directory.There are
unavoidable security problems surrounding use of the -exec action;
you should use the -execdir option instead.
Although you asked for a find/exec solution, as Mark Reed suggested, you might want to consider piping your results to xargs. If you do, make sure to use the -print0 option with find and either the -0 or -null option with xargs to avoid unexpected behaviour resulting from whitespace or shell metacharacters appearing in your file names. Also, consider using the + version of -exec (also in the manual) as this is the POSIX spec for find and should therefore be more portable if you are wanting to run your command elsewhere (not always true); it also builds its command line in a way similar to xargs which should result in less invocations of rename.
Don't think there's a way you can do this with just find, you'll need to create a script:
#!/bin/bash
NEW=`echo $1 | sed -e 's/file_/mywish_/'`
mv $1 ${NEW}
THen you can:
find ./ -name 'file_*' -exec my_script {} \;

why find need "{} \"?

I use command of find, for example:
find . -name "*.log" -exec grep "running" {} \;
why the command of find need {} , a blank and \?
This is because of the -exec parameter: the {} is a placeholder for the file that will be passed to the command.
the semicolon (;) tells find that the -exec argument list is over, but since ; is also a shell operator, you need to escape it so that it reaches find: \;
-exec works like this: for every file that is found, the first argument after -exec (the command) is executed and all parameters up until the ; are passed as arguments to the command. The {} is then replaced by the current filename that is found by find.
{} is a placeholder for path, which find replaces with the actual found path.
\; terminates find's exec arguments. Without \ shell would treat it as shell statement terminator, hence it needs to be quoted with \ for the shell to pass ; it to find.
I'd say that ; was an unfortunate choice for find exec command terminator.
Note that {} \; sequence can be replaced with {} +:
-exec command {} +
This variant of the -exec action runs the specified command on
the selected files, but the command line is built by appending
each selected file name at the end; the total number of invoca‐
tions of the command will be much less than the number of
matched files. The command line is built in much the same way
that xargs builds its command lines. Only one instance of `{}'
is allowed within the command. The command is executed in the
starting directory.
Just read the manpages
-exec command ;
Execute command; true if 0 status is returned. All following
arguments to find are taken to be arguments to the command until
an argument consisting of `;' is encountered. The string `{}'
is replaced by the current file name being processed everywhere
it occurs in the arguments to the command, not just in arguments
where it is alone, as in some versions of find. Both of these
constructions might need to be escaped (with a `\') or quoted to
protect them from expansion by the shell. See the EXAMPLES sec‐
tion for examples of the use of the -exec option. The specified
command is run once for each matched file. The command is exe‐
cuted in the starting directory. There are unavoidable secu‐
rity problems surrounding use of the -exec action; you should
use the -execdir option instead.
The backslash is an escape to protect the semicolon from being misinterpreted.
The braces are placeholders for the full path outputted by find.

Resources