Linux 中的 find 命令是查找文件和目录的极好用的工具。关于 find 命令,可以查看我们先前分享的文章:关于 find 命令的15个超级有用的例子
我们可以把找到的文件,执行一些特定的操作。比如,我们找到了一些扩展名为 .jpeg 的文件,可以将其扩展名统一改为 .jpg。
不能仅通过管道将查找命令的输出重定向到另一个命令,因为它不会那么简单。
有两种方法可以对find命令的结果执行其他命令:分别是使用 xargs 和 exec 命令。
关于 xargs 命令的文章,可以参考:如何在Linux中使用xargs命令
本文将重点介绍如何将 find 与 exec 组合使用。
exec 与 find 命令一起使用
使用 exec 执行 find 命令的基本语法如下:
find [path] [arguments] -exec [command] {} \;
上述语法中:
[command] 是要对 find 命令的输出结果执行的操作(后续命令);
{} 是一个占位符,用于保存 find 命令输出的结果;
\; 表示对于每个找到的结果,都会执行一次[command],在这里需要对分号 ; 进行转义,因此需要在前面使用反斜杠 \ 。
注意,在 {} 和 \; 之间需要有一个空格。
还有另外一种用法,与上面的方式有所不同,如下:
find [path] [arguments] -exec [command] {} +
这里,加号 + 表示对于 find 命令的所有结果,[command] 只会执行一次,也就是所有结果都作为参数一起传递给 [command]。这里的加号 + 不需要使用反斜杠 \ 进行转义。
我们来回顾一下,在 find命令实例 中使用过的例子,来说明一下 {} \; 和 {} + 的区别。
{} \; 如同下面的执行(为每一个结果都单独执行一次):
ls file1.txt
ls file2.txt
ls file3.txt
{} + 如下所示(使用所有的输出作为参数,执行命令一次):
ls file1.txt file2.txt file3.txt
通过如上表述,使用 {} + 似乎是个更好的选择,但事实恰恰相反。如果 find 命令有50个结果,就不能将它们作为参数一起传递,因为在命令行中有最大长度限制。
这就是为什么你最好使用 {} \; 的原因,除非你特别清楚将要执行的操作。
find 和 exec 命令一起使用的一些例子
接下来我们分享一些常用的关于 find 和 exec 命令结合使用的例子,以便大家能更好的理解它们。
1. 查找和显示文件属性
下面的这个例子,将显示 tmp 目录下所有的 lock 文件,并显示它们的属性:
sudo find tmp/ -type f -name *lock -exec ls -l {} \;
结果如下:
sagar@LHB:~$ sudo find tmp/ -type f -name *lock -exec ls -l {} \;-r--r--r-- 1 gdm gdm 11 Jul 17 08:01 tmp/.X1024-lock-r--r--r-- 1 gdm gdm 11 Jul 17 08:01 tmp/.X1025-lock
2. 查找并重命名文件
使用 find 和 exec 可以很方便的重命名文件(重命名文件,可以使用 mv 命令)。
sudo find home/sagar/Downloads/ -type f -name 'ubuntu*' -exec mv {} {}_renamed \;
上面的命令查找以 ubuntu 开头的文件,并将其存储在占位符中。一旦该过程结束,它将在存储在占位符中的每个文件的末尾添加 “_renamed”。

3. 收集并保存文件的大小
在本例中,我们将展示如何收集特定目录下可用文件的大小,并创建一个文件来保存给定的输出。
我们将在 tmp 目录下收集每个文件的大小,并将输出保存在 root 目录下,文件名为:du_data.out
sudo find tmp/ -type f -exec du -sh {} \; > root/du_data.out
那现在,我们在 root 目录下查看一下创建的文件内容是什么:

4. 使用特定参数删除文件
自动删除文件时请格外小心。如果你不注意,这可能是灾难性的。可以将交互式删除与 rm -i 一起使用,也可以先查看 find 命令的结果。
find 与 exec 命令组合使用的另一个常见例子是查找大于某个值的文件并将其删除。比如,清理一些大的日志文件。
下面这个例子,我们将会删除桌面上大于 100MB 的文件。
find ~/Desktop -size +100M -exec rm {} \;
类似,也可以根据文件创建的时间来删除,比如,我们删除超过10天的文件:
sudo find /tmp/ -type f -mtime +10 -exec rm {} \;
上述命令中的 -mtime 选项,表示文件的修改时间,后面的数字单位是天,+10表示超过10天。
5. 使用特定的工具执行操作
在某些情况下,你可能希望在找到文件后,启动某些工具或软件包,来执行后续操作。
比如,我们搜索 mp3 文件,然后运行 id3v2,来显示 mp3 文件的详细信息:
find . -name "*.mp3" -exec id3v2 -l {} \;
id3v2 是一个包,它将显示有关 mp3 文件的详细信息,-l 用于显示与找到的 mp3 相关的每个 mp3 标记。

6. 更改文件和目录的所有权
使用 find 和 exec 组合命令,还可以更改文件或目录的所有权,这也是一个很常见的应用场景。
下面的例子,我们查找用户 sagar 所拥有的文件,然后将其用户所有权更改为 milan:
sudo find /home/sagar/disk/Downloads -user sagar -type f -exec chown milan {} \;

7. 更改文件权限
另外一个很常用的例子,就是更改文件的权限。关于文件权限,可以参考我们之前的文章:你了解 Linux 文件权限和所有权吗?
看下面的例子:
sudo find /home/sagar/disk/Downloads -type f -exec chmod 644 {} \;
上述命令,用于查找 Downloads 目录下所有的文件(使用 -type f 选项),然后将其权限更改为 644。

8. 为每个文件收集md5sum
在下面的例子中,我们将演示如何为 /tmp 目录下的每个可用文件收集 md5sum 信息:
sudo find /tmp/ -type f -exec md5sum {} \;
如下图所示,上述命令会打印每个可用文件的名称和 md5sum 信息:

那么,怎么样才能将上面的输出保存到一个文件中呢?可使用如下命令:
sudo find /tmp/ -type f -exec md5sum {} \; > /Documents/checksumdata.out
9. 将 exec 与 grep 命令组合使用
find 命令根据文件名查找,grep 命令可在文件内容中查找。
如果你对 grep 还不太熟悉,可以参考:在Linux中怎样进行 grep 搜索呢?通过例子来学习几个常用的方法
使用 find 和 grep 以及 exec 命令的组合,就可以得到一个功能强大的搜索工具。
比如下面的命令,搜索扩展名为 .hbs 的文件,然后使用 grep,将在这些文件中,搜索包含字符串 "excerpt" 的内容。
find . -type f -name "*.hbs" -exec grep -iH excerpt {} \;
使用 -H 选项,grep 命令将显示每个匹配的文件名。以下是输出:
sagar@LHB:~/Downloads/casper-hyvor$ find . -type f -name "*.hbs" -exec grep -iH excerpt {} \;./author.hbs: <div class="post-card-excerpt">{{bio}}</div>./partials/post-card.hbs: {{#if excerpt}}./partials/post-card.hbs: <div class="post-card-excerpt">{{excerpt}}</div>./post.hbs: {{#if custom_excerpt}}./post.hbs: <p class="article-excerpt">{{custom_excerpt}}</p>./tag.hbs: <div class="post-card-excerpt">
10. 使用多个 exec 命令
是的,你可以在单个 find 命令中,组合使用多个 exec 命令。
我们对上一个命令做一下修改,使用两个 exec 命令:
find . -type f -name "*.hbs" -exec echo {} \; -exec grep excerpt {} \;
上述命令,首先搜索扩展名为 .hbs 的文件,然后第一个 exec 命令用于显示搜索到的文件名称;然后,第二个 exec 命令将在这些文件中搜索包含字符串 "excerpt" 的内容。
其输出与上一个命令略有不同:
sagar@LHB:~/Downloads/casper-hyvor$ find . -type f -name "*.hbs" -exec echo {} \; -exec grep excerpt {} \;./index.hbs./page.hbs./default.hbs./author.hbs<div class="post-card-excerpt">{{bio}}</div>./error-404.hbs./error.hbs./partials/icons/twitter.hbs./partials/icons/fire.hbs./partials/icons/lock.hbs./partials/icons/loader.hbs./partials/icons/rss.hbs./partials/icons/avatar.hbs./partials/icons/facebook.hbs./partials/post-card.hbs{{#if excerpt}}<div class="post-card-excerpt">{{excerpt}}</div>./post.hbs{{#if custom_excerpt}}<p class="article-excerpt">{{custom_excerpt}}</p>./tag.hbs<div class="post-card-excerpt">
find 是一个功能强大的命令,用于根据给定条件搜索文件,exec 命令可以让我们很方便的处理 find 命令的输出结果。我们上面介绍的也只是一个大概,在实际应用中使用 find 与 exec 命令的组合,为我们在 Linux 命令行中执行操作提供了无限可能。
以上就是本次分享全部内容,欢迎讨论。




