Home  >  Article  >  php教程  >  Find command in action

Find command in action

高洛峰
高洛峰Original
2016-12-14 17:28:301410browse

By the way, the most commonly used commands in Linux are awk, grep, vim, and find. Today we will take a detailed look at the use of the find command.

Let’s take a simple example first:

Shell code

find . -name "*.java"  # 递归查找当前目录下所有java文件

Among them:
. indicates that the search path is the current directory (you can also specify it as another project directory, such as: ~/workspace/login)
-name indicates the target file name or directory name of the search (shell wildcards are allowed)

Usually the above command can already be used Complete 80% of your daily work needs, but to complete the other 20%, you must have a deeper understanding of the find command...

Now suppose you need to find the two files Test.java and TEST.java. At this time What should you do?
Maybe you will execute find . -name "Test.java" and find . -name "TEST.java" twice

Although the result is correct, is there an easier way? The answer, of course, is

Shell code

find . -iname "test.java"   # -iname 与-name参数含义一样,但是忽略大小写

Did you notice, is it more elegant...

Now we go one step further, suppose we need to list all the files named study in the ~/scripts directory. What should we do? ?

Before you don’t understand the find command, you may need to use a shell for loop to recursively traverse the directory, and then determine whether each found study is a file (it may be a directory named study), and output it if it is indeed a file. Having said so much, this method is really cumbersome and abnormal, but if you understand the find command, then just one line!

Shell code

find ~/scripts -type f -name "study"

The -type parameter is used to specify the target type of the search, and f means ordinary files. -type has other commonly used parameter values: f-file, d-directory

Now you know:
1. How to specify the find search path
2. How to specify the target type of find search (-type)
3. How to specify the file name or directory name to be searched by find (-name / -iname)

There are really a lot of things, but we have to move on, the find command also has many useful parameters.

The find command defaults to recursive search, and its search algorithm should be what we often call depth-first traversal (you can specify the breadth-first traversal algorithm by specifying the -depth parameter), but sometimes we want to search only in the current directory, or You can specify the depth of the recursive search. What should you do at this time? Two simple words

-maxdepth: Specify the maximum depth of the directory when searching recursively. If it is 1, it means searching only in the current directory
-mindepth: Specify the minimum depth of the directory when searching recursively

Now let’s look at two examples (first Do not try to run):

Shell code

find . -name "*.java" -maxdepth 3  
find . -maxdepth 3 -name "*.java"

There seems to be no difference between these two commands, but the running effect is indeed very different (especially when there are many files and very deep directories), or on some machines, the first One form cannot run at all, why?

Because the first command will first find all java files, and then filter out the files that meet the depth conditions. This is very, very inefficient, while the second command It only searches for the target file in the 1-3 directory, without recursively traversing the entire file tree, so it is very efficient.

When I execute the first command on my machine, the following warning pops up:
find: warning: you have specified the -maxdepth option after a non-option argument -name, but options are not positional (-maxdepth affects tests specified before it as well as those specified after it). Please specify options before other arguments.


Okay , you now have two more powerful tools in your hands - maxdepth and -mindepth (these two parameters can improve your search efficiency and Zhuangbility)

The find command also has several useful parameters
-mtime: file content Last modification time
-atime: file last access time
-ctime: file meta information last modification time (such as file permissions)

These parameters need to be followed by an integer value, eg:

Shell code

find . -mtime 1  -name "*.java"     # 在当前目录下递归查找距离现在整1天修改的java文件  
find . -mtime -1 -name "*.java"     # 在当前目录下递归查找1天内修改的java文件  
find . -mtime +1 -name "*.java"     # 在当前目录下递归查找1天前修改的java文件

If you need to find modified files within a certain period of time, these commands are very effective (students engaged in operation and maintenance should use them frequently)

There are so many parameters mentioned (-name, -iname, -type, -mindepth , -maxdepth, -mtime, etc.), I believe you already know something about the find command.
Now let’s take a look at a good friend of the find command----xargs

Usually we need to perform a certain function on the found files. Some actions, for example, I want to find all the java files that use StringUtils in a certain project directory. What should I do at this time?

Method 1 we can use eclipse search, method 2 we can write scripts, method 3 just one line...

Shell code

find ~/worksapce/project -name "*.java" | xargs grep "StringUtils"

其中: 
find ~/worksapce/project -name "*.java" 将会在家目录下workspace/project中递归查找所有java文件 
xargs grep "StringUtils" 表示在文件中(find命令查找出的结果集)查找含有StringUtils字样的文件 

也许有人一开始会这样写:find ~/worksapce/project -name "*.java" | grep "StringUtils" 
这个命令执行将不会产生任何结果,而原因就是因为没有使用xargs! 

现在我们就来说说xargs:xargs是用来把输入流转化为参数的命令(默认把输入流中的空白字符譬如"\n"(换行)替换成" "(空格)) 

Shell代码 

$ cat test   
a  
b  
c  
d  
e  
$ cat test | xargs  
a b c d e

ind命令将查找出的每一个文件名或目录名默认用"\n"分割,然后通过管道 | 作为输入流传递给grep命令,但是grep命令要求输入流必须是参数的形式,譬如:grep "target" file1 file2 所以必须使用xargs重新将输入流转换为参数 

说到这里,一些比较严谨的同学也许会说,这样的命令:find ~/worksapce/project -name "*.java" | grep "StringUtils" 是不严谨,不安全的(这里还谈不上不安全,毕竟只是一个grep命令,但要是变成xargs rm -rf 那就危险了),原因就是find命令默认用"\n"分隔结果列表,而xargs会把"\n"转化成空格,所以当文件路径或者文件名含有"\n"这些字符时,就会被错误替换,这时候你在执行个rm -rf ,哦, 卖糕的... 

所以我们应该养成好习惯,这样写 

Shell代码 

find ~/worksapce/project -name "*.java" -print0 | xargs -0 grep "StringUtils"

print0用'\0'(空字符)分隔结果列表,xargs -0 只会将'\0' 替换成空格,这样就不会出现刚才所说的问题了.... 


关于find命令,我就说到这里,赶紧尝试吧... 

更多Find命令实战相关文章请关注PHP中文网!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn