In-depth understanding of find xargs grep and pipes

Question:
I believe everyone knows the command to search for files containing fixed strings in a directory:

find . -name '*.py' |xargs grep test
When I first started, I was not familiar with the xargs command, so the command I used directly was

find . -name '*.py' |grep test
result is not what I expected. This command just finds out the case where the filename *.txt has test.

Here I will study what exactly xargs does to make the results different.

Parameters and standard input:
These two words are very common in Linux commands. But parameters and standard input are actually different. Many of the commands we use every day, such as ls -lah. l, a, h, . are all parameters of the command ls. As for standard input, let's say it's some kind of streaming data. Generally speaking, the source of stream data for standard input is our terminal input. Among Linux commands, some commands can receive standard input, and some cannot. Like the above ls, it can only receive parameters, not standard input. Like cat command or echo command, these are ok.

How to tell if a command accepts standard input? It's very simple, when you type the command Enter, the terminal will wait to receive your input, for example, when you type cat in the terminal, the terminal will wait for you to enter characters, when you enter some characters, then press Ctrl-C to send termination symbol. At this time, the cat command receives the standard input and executes the command, that is, the standard output (screen) of the content just typed is output.

pipeline:
The role of the pipe is to use the standard output of the preceding command as the standard input of the following command. It should be noted here that the following commands receive standard input, so if the command does not support receiving standard input, then pipes cannot be used directly. For example, the commonly used ls command can only use parameters, not standard input, so [command] | ls cannot be used. And commands such as echo or cat will do. Then there must be a way to combine these commands that cannot use standard input with pipes, and then xargs comes into play.

xargs command:
The xargs command is generally used to convert the standard input into various formatted parameters, so the command [command 1] | xargs [command 2] is to convert the standard output result of command 1 into the standard of xargs through the pipe | Input, and then xargs then turns this standard input into an argument and passes it to [command 2]. This way, with the xargs command, we can use commands that do not accept standard input later in the pipeline. For example [command 1]|xargs ls, is it familiar?

find and grep:
With the above knowledge points, we can finally answer the initial question here. Why are the results of the commands

find . -name '*.py' |grep test
and

find . -name '*.py' |xargs grep test
different?

Let's start by looking at the grep manual. Via the man grep command.

DESCRIPTION
       grep searches the named input FILEs (or standard input if no files are named, or if a single hyphen-minus (-) is given as file name) for lines containing a match to the given PATTERN. By default, grep prints the matching lines .
Here you can see that grep supports standard input.

Suppose the following file exists in the directory:

$ ls
Altitest.py python.py runora.py test.py TransferFile.py
Then for the first command find . -name '*.py' |grep test, the standard output of the previous command is used as The standard input is passed to grep test, then grep looks for test characters from these standard inputs, which is a character stream composed of file names

$ find . -name '*.py' |grep test
./Altitest.py
./test.py
You can see that these file names are finally selected.

For the second command find . -name '*.py' |xargs grep test, through xargs, the file name obtained by find becomes the parameter passed to the following grep, then these file names are real file identifiers at this time , after grep receives it, it will search for strings in each file in the normal way.

#find . -name '*.py' |xargs grep test
./runora.py:testConn = cx_Oracle.connect('user/passwd@tns')
./runora.py:testCursor = testConn.cursor()
./runora.py:testCursor.execute("select * from table")
./runora.py:rows = testCursor.fetchall()
./runora.py:testCursor.close()
./runora.py:testConn.close()
Here is a clear understanding of the functions of find, grep, xargs and pipes .

xargs also has the role of specifying the location of arguments. Suppose we want to put all the .py files in the directory into the Python directory, we can use the command
find . -name '*.py' | xargs -I {} mv {} ./Python
parameter -I specifies the command before the pipeline The position of the command after the pipe that should be used as an argument.

When we look at many command manuals, the manual will explain how to use the command. For example
grep [OPTIONS] PATTERN [FILE...], that is, the last position of the command is the filename [FILE].
It should be noted here that the file name [FILE] is also a parameter.

Massive it video acquisition

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326134625&siteId=291194637