你将看到的第一个命令是find。这是个用于搜索文件的命令,它极其有用,但Linux初学者常常觉得它不易使用,这不仅仅是因为它有选项、测试和动作类型的参数,还因为其中一个参数的处理结果可能会影响到后续参数的处理。在深入研究这些选项、测试和参数之前,让我们首先看一个非常简单的例子,它用来在本地机器上查找名为test的文件。为了确保你具有搜索整个机器的权限,请以root用户身份来执行这个命令:
find / -name test -print
根据你所使用系统的不同,你可能还会找到其他几个名称也为test的文件。正如你可能猜测的那样,这个命令的含义是:从根目录开始查找名为test的文件,并且输出该文件的完整路径。这非常简单。
然而,这个命令的执行确实需要花费很长的时间,并且网络上的Windows机器的硬盘也会高速转动。这是因为Linux机器挂载(使用SAMBA)了一大块Windows机器的文件系统,看起来似乎是Windows文件系统也被搜索了,尽管我们知道要查找的文件应该在Linux机器上。
这就是我们要介绍的第一个选项发挥作用的时候了。如果你指定-mount选项,你就可以告诉find命令不要搜索挂载的其他文件系统的目录。
# find / -mount -name test -print
我们仍然能找到文件,但这次搜索速度会更快,同时也不必再搜索挂载的其他文件系统。find命令的完整语法格式如下所示:
find [path] [options] [tests] [actions]
path部分很容易理解:你既可以使用绝对路径,如/bin,也可以使用相对路径,如.。如果需要,你也可以指定多个路径,如find /var /home。find命令有许多选项可用,下表列出了一些主要的选项。
-maxdepth 2
# find / -mount -maxdepth 3 -name test -print
下面是测试部分。可以提供给find命令的测试非常多,每种测试返回的结果有两种可能:true或false。find命令开始工作时,它按照顺序将定义的每种测试依次应用到它搜索到的每个文件上。如果一个测试返回false, find命令就停止处理它当前找到的这个文件,并继续搜索。如果一个测试返回true, find命令将继续下一个测试或对当前文件采取行动。下表只列出了最常用的测试,请参考find命令的手册页以了解所有可以使用的测试。
你还可以用操作符来组合测试。大多数操作符有两种格式:短格式和长格式,如下表所示。
你可以通过使用圆括号来强制测试和操作符的优先级。由于圆括号对shell来说有其特殊的含义,所以你还必须使用反斜线来引用圆括号。此外,如果你在文件名处使用的是匹配模式,你就必须在模式上使用引号以确保模式没有被shell扩展,而是直接传递给find命令。例如,如果你想写一个测试“搜索的文件比文件X要新,或者文件名以下划线开头”,你可以这样写:
\(-newer X -o -name "_*" \)
我们将在下一个“实验解析”部分之后举这样一个例子。
首先创建两个文件hello1 和hello2
touch hello1
touch hello2
超找比hello1新的文件,预判结果肯定是hello2
# find . -newer hello1 -print
.
./hello2
这个结果看起来不错,不过在结果中还包括了当前目录,而这并不是你想要的,你只对普通文件感兴趣。所以你会增加一个额外的测试-type f:
$ find . -newer hello1 -type f -print
./hello2
它是如何工作的呢?你指定find命令应该在当前目录(.)中搜索比文件hello1 要新的文件(-newer hello1 ),如果这个测试通过,然后再测试这个文件是否是一个普通文件(-type f)。最后,你使用前面已经讲过的-print来确认搜索到的文件。实际上不加-print也没问题,如下所示:
$ find . -newer hello1 -type f
./hello2
现在来查找以下划线开头的文件或比hello1文件要新的文件,但在两种情况下都必须是普通文件。这个例子将演示如何使用圆括号来对测试进行组合:
创建一个带下划线的文件:并更新其他两个文件的时间戳
lkmao@ubuntu:/big/work/shell$ touch _hello3
lkmao@ubuntu:/big/work/shell$ touch hello1
lkmao@ubuntu:/big/work/shell$ touch hello2
lkmao@ubuntu:/big/work/shell$ find . \( -name "_*" -or -newer hello1 \) -type f -print
./_hello3
./hello2
lkmao@ubuntu:/big/work/shell$
可以看出完成这个任务并不是很困难。你必须转义圆括号使得它们不会被shell处理,而且还需要将*号用引号括起使得它被直接传递给find命令。
现在你已可以可靠地搜索文件了。下面来看看在发现匹配指定条件的文件之后,你可以执行的动作。下表只列出了最常见的动作,完整的动作列表请见find命令的手册页。
-exec和-ok命令将命令行上后续的参数作为它们参数的一部分,直到被\;序列终止。实际上,-exec和-ok命令执行的是一个嵌入式命令,所以嵌入式命令必须以一个转义的分号结束,使得find命令可以决定什么时候它可以继续查找用于它自己的命令行选项。魔术字符串{}是-exec或-ok命令的一个特殊类型的参数,它将被当前文件的完整路径取代。
上面的解释可能并不容易理解,但通过一个例子可以将其解释得更清楚。我们来看一个比较简单的例子,它使用一条非常安全的命令ls:
lkmao@ubuntu:/big/work/shell$ find . -newer hello1 -type f -exec ls -l {} \;
-rw-rw-r-- 1 lkmao lkmao 0 6月 14 18:14 ./hello2
lkmao@ubuntu:/big/work/shell$
如你所见,find命令非常有用。你只需通过一点练习就可以很好地掌握它。无论如何,这点练习是完全值得的,所以请使用find命令来进行实验。
小结