linuxja 2017-04-25
上一课 Linux探索之旅 | 第二部分第八课:RTFM 阅读那该死的手册,我们学习了很重要的技能:如何阅读使用手册。
这一课不难,但挺重要的。
之前的课程Linux探索之旅 | 第二部分第三课:文件和目录,组织不会亏待你中,我们已经见识过,Linux下文件的组织形式是很特别的,跟Windows不一样。
我们也用ls / 这个命令来列出根目录下的所有目录,有/bin,/etc,/var,/home,等等。而这些目录下又有子目录和文件,错综复杂。
ls /
这些目录中有一部分是历史遗留的,从Unix时代就有了。问题是:我们如何在这“茫茫文海”中查找我们需要的文件。
“人潮人海中,有你有我。相遇相识,相互琢磨”(黑豹乐队的《无地自容》),小编你可以了...
不要担心,这一课我们就来学习Linux中用于文件查找的工具。
有的工具查找起来快,但是不全面;有的比较慢,但是全面。
一起来学习吧。
第一种查找文件的方法可以说是很简单的。用到的命令是locate。
locate是英语“定位”的意思。这个命令用于定位要查找的文件,而且此命令很快。
locate命令的用法也很直观,后接需要查找的文件名(当然也可以用正则表达式)。
例如我们来查找一个叫做 renamed_file的文件:
locate renamed_file
可以看到locate命令帮我们找到了renamed_file文件,位于 /home/oscar/linux_c目录下。
我们再来用locate查找france文件(France是“法国”的意思。):
我们运行locate france后,终端列出了所有包含france的文件和目录。
所以locate命令是搜索包含关键字的所有文件和目录。
在使用locate命令查找文件时,大家可能会遇到这样的问题:我刚创建的文件,为什么用locate命令查找不到呢?
这正好是locate命令的缺陷,我正要说到:locate命令不会对你实际的整个硬盘进行查找,而是在文件的数据库里查找记录。
locate命令的原理如下图所示:
对于刚创建不久的文件,因为它们还没被收录进文件数据库,因此locate命令就找不到其索引,自然就不会返回任何结果。
Linux系统一般每天会更新一次文件数据库。因此,只要你隔24小时再用locate查找,应该就能找到你刚创建的文件了。
但是你会说:“臣妾不想等这么久啊。难道哀家要在这深宫之中等候多时么?”
当然不是,甄嬛不会一直赢的,皇后总有出头之日。
我们可以用updatedb命令强制系统立即更新文件数据库。但是updatedb命令只能由root用户执行。
update是英语“更新”的意思。db是英语database的缩写,表示“数据库”。所以连起来就是“更新数据库”。
因此我们可以这样:
sudo updatedb
这个命令执行需要一点时间,小编执行的时候等了几分钟才完毕。
一旦执行成功,你再用locate查找你刚才创建的文件,就可以找到了。
总结一下:locate命令方便快捷,易于使用。但缺点也很明显:
locate命令会列出所有在文件数据库中找到的内容,有时候结果太多了,太繁杂。
locate命令不能找到一天之内刚创建的文件,除非你先用root身份运行updatedb命令来更新文件数据库。
当locate命令不够用时,我们需要一个更强大的命令,它就是find命令。
find是英语“找到”的意思,find命令也用于查找文件。
find命令是查找文件的利器,而且它可以让我们对每个找到的文件做后续的操作。find命令非常强大,可以做很多事情,因此也比较复杂。
find命令可以说是Linux中最常用的命令之一了。所以,一起来探秘吧。
与locate命令不同,find命令不会在文件数据库中查找文件的记录,而是遍历你的实际硬盘。
所以,如果你的硬盘容量很大的话,那find命令会查找比较久。
find命令的原理如下图所示:
find命令的这种“耿直”的查找方式保证了我们不会遗漏一天之内创建的文件。但这绝对不是find的唯一强大之处,远远不是。
find命令的用法是这样的:
find 《何处》《何物》《做什么》
这几个参数中,只有《何物》是必须指定的,也就是要查找什么。
何处:指定在哪个目录中查找。此目录的所有子目录也会被查找。与locate命令的查找所有文件数据库的所有记录不同,find命令可以限定查找目录,比如我们可以只让find查找/home目录。默认地,假如我们没有给出《何处》这个参数,那么find命令会在当前目录及其子目录中查找。
何物:也就是要查找什么。我们可以根据文件的名字来查找,也可以根据其大小来查找,也可以根据其最近访问时间来查找,等等。这个参数是必须的。
做什么:用find命令找到我们要的文件后,可以对每个文件做一定的操作,称为“后续处理”。默认地,假如不指定这个参数,那么find命令只会显示找到的文件,不会做其他事情。
根据文件名查找
我们首先来学习最基本的查找:用文件名来查找。
首先,我们定位到用户的家目录中(对于小编来说是/home/oscar),然后我要在当前目录及其子目录中查找france1.jpg这个文件。
find -name "france1.jpg"
这里,我们用-name参数指定了文件名字,是france1.jpg,用双引号括起来。不加双引号或者用单引号也是可以的。
name是英语“名字”的意思。
经过了一点时间,查找才停止,因为find命令会遍历指定的所有目录。
最终,find命令找到了france1.jpg这个文件,位于/home/oscar/Photos 目录下。
如果find命令没有结果显示,那么表示此文件不存在。
因为我们没有指定《何处》这个参数,所以find命令就会在当前目录(~,也就是用户的家目录中,/home/oscar)及其子目录中查找。
假如,现在我位于我的家目录中,我却想在其他目录中进行查找,怎么办呢?
那就须要指定《何处》这个参数了。
例如,我要在/var/log目录下查找名为syslog的文件,我应该这么输入:
find /var/log -name "syslog"
但是,作为普通用户的oscar,没有权限在/var/log的子目录中查找。因此,显示:
Permission denied
permission是“许可”的意思,denied是“否决”的意思。就是说“权限被否决”,没有权限做这事。
我们可以切换成root身份,再来执行查找。
sudo su find /var/log "syslog"
可以看到,切换成root后,就可以查找了。并且找到了两个结果:
/var/log/installer/syslog /var/log/syslog
在上面的查找中,我们的参数如下:
何处:/var/log(及它的子目录)
何物:syslog
没有指定《做什么》参数,因此find命令默认显示了查找到的文件。
我们注意到了:与locate命令不同的是,find命令只会查找完全符合《何物》的字符串表示的文件。locate会查找所有包含关键字的文件。比如,如果要用find来找thing这个文件,那么只会找到名字就是thing的文件;而locate命令会查找到比如thing,thing1,onething,twothings这样的文件。
因此,我们用find查找syslog文件时,就不会查找到syslog2这样的文件。
不过我们可以用我们之前学过的通配符:*(星号)来实现匹配多个名称。
例如,我要查找所有以syslog这个关键字开头的文件,可以这样来实现:
find /var/log -name "syslog*"
可以看到,在syslog之后加了之后,就会匹配凡是以syslog开头的文件了,因为号是匹配一个或多个任意字符。
那聪明如你肯定想到了,如果要查找以syslog结尾的文件,可以用:*syslog
那你肯定也知道,如何查找包含syslog这个关键字的文件,可以用 *syslog*
那如果我要在整个硬盘里查找怎么做呢?很简单:
find / -name "syslog"
在Linux的根目录查找很花时间,而且,如果你不是以root身份查找的话,就会有很多目录提示你“无权限访问”。
如果你不知道你要找的文件的名称,那怎么办呢?
不要担心,还有其他方式来查找文件的。
我们先来看如何根据文件大小查找。
例如,我们可以查找/var中大小超过10M的文件(当然你要以root身份):
find /var -size +10M
这次,我们使用了-size参数,来指定查找文件的大小。size是英语“尺寸,大小”的意思。
后面紧跟的+10M表示大于10兆字节。
M是兆,也就是10的6次方;平时我们所说的Ko,Mo,Go其实分别是千字节,兆字节,千兆字节的意思。
一个字节是8位二进制数。我们说硬盘512G,就是硬盘容量有512千兆字节(虽然实际容量是不到的,暂时不深究)。
如果我们要查找小于指定大小的文件,可以用减号。例如:
find /var -size -50K
表示查找小于50Ko的文件。
find /var -size +20G
表示查找大于20Go的文件。
如果没有加减号,则查找大小等于指定数值的文件。
如果你记得你近7天里在家目录中访问过JPG格式的图片,但是你忘记它们的名字了,如何查找呢?
可以使用-atime参数。atime是access和time的缩写,access是英语“访问,进入”的意思,time是英语“时间”的意思。
可以这样查找:
find -name "*.jpg" -atime -7
-atime参数后面紧跟的-7表示7天之内,减号的作用是表示小于。
我们可以指定查找的文件类型,我们知道Linux中文件的类型大致分为两种:目录和文件。
因此,我们可以用-type参数来指定查找的文件类型。type是英语“类型”的意思。
-type d:只查找目录类型。d是directory的首字母,表示“目录”。
-type f:只查找文件类型。f是file的首字母,表示“文件”。
如果不用-type参数指定类型,那么find命令默认是查找目录和文件的。比如说,有syslog这个文件,和syslog这个目录,那么find会把他们都查找出来。
用法如下:
find /var/log -name "mysql" -type d
可以看到只查找到了mysql这个目录。
到目前为止,我们只是使用了find的基本功能。我们并没有指定《做什么》这个参数,也就是还没对查找到的结果做任何操作。
当然了,默认地,find命令会显示每个查找到的文件。
事实上,
find -name "*.jpg"
等价于
find -name "*.jpg" -print
-print参数用于打印结果。print是英语“打印”的意思。
默认地,find命令只列出查找到的文件,但是我们可以将其用格式化的方式打印出来。**
我们可以使用-printf参数。是不是想起了C语言中的printf函数?是的,printf是print formatted的缩写,表示“格式化打印”。
例如,我们可以这样打印查找到的内容:
find ~/Photos -name "*.jpg" -printf "%p - %u\n"
我们在-printf参数后面写了"%p - %u\n",这个格式字符串的意思如下:
%p:文件名。
-:就是一个短横。
%u:文件的所有者,这里是小编的用户名,所以是oscar。
\n:用于换行。
可以看到,用法和C语言的printf函数很类似。
假如我要删除查找到的文件,我可以用-delete参数。用法很简单:
find -name "*.jpg" -delete
将会删除当前目录及其子目录下所有以.jpg为后缀的文件。而且不会有确认提示。所以慎用-delete参数。
使用-exec参数,可以后接一个命令,对每个查找到的文件进行操作。
exec是execute的缩写,是英语“执行”的意思。
假设我想要将当前目录下所有查找到的JPG文件的访问权限都改为600,那么我们可以这样做:
find -name "*.jpg" -exec chmod 600 {} \;
就是说对于每个找到的.jpg结尾的文件,都进行-exec参数指定的操作:
这个操作不必用双引号括起来。
{} 会用查找到的每个文件来替换。
\; 是必须的结尾。
虽然-exec参数一开始有点看不懂其用法,但是慢慢地你会发现,这个参数太强大了,你可以对查找到的文件做任何你想要的操作。
如果你对于没有确认提示不太放心,你可以将-exec参数换成-ok参数,用法一样,只不过-ok参数会对每一个查找到的文件都做确认提示,输入y加回车表示对此文件进行此操作;输入n加回车表示对此文件不进行此操作。
为了在Linux硬盘中查找一个文件,我们可以用locate命令。这个命令很快,因为它不会实际遍历硬盘,而是在被称为文件数据库的记录里查找,所以它找不到刚添加的文件。为了更新文件数据库,我们可以用root用户身份运行updatedb命令。
find命令比locate命令更强大,用法更多样。它会遍历实际的硬盘来查找文件,所以更慢,但是更精确。find命令可以跟三个参数:《何处》,《何物》,《做什么》。
可以根据文件的名字来查找,用-name参数;根据大小来查找,用-size参数;根据最后访问时间来查找,用-atime参数。等等。
查找到了文件,我们也可以选择不显示,而是删除文件,用-delete参数,或者对文件执行命令,用-exec参数。
今天的课就到这里,一起加油吧!
下一课:Linux探索之旅 | 第二部分测试题