如何在文件集更改时运行 Linux 命令

了解如何在监视的一组文件中的任何文件发生更改以及创建新文件时运行 Linux 命令。我们向您展示如何使用这个灵活的工具。
输入命令
您可以使用 cron
将命令设置为在 Linux 中的特定时间运行。它简单、可靠且灵活。但是,如果您需要在文件更改或将新文件添加到目录时执行命令怎么办?这也是可能的,而且有不止一种方法可以做到。 entr
命令是实现该功能的一种令人耳目一新的直接方式。
某些系统(例如 Hugo 静态网站生成器)具有在文件更改或将新文件添加到网站时自动重建网站的功能。这个小功能会对您的工作流程产生重大影响。使用 Hugo,您可以在编辑构成网站的文件时在浏览器中使用网站的开发版本。每次您保存更改或创建文件时,网站都会在几毫秒内重建,并将更改推送到您的浏览器。即时反馈太棒了。
entr
命令将这种类型的功能用于任何文件集。检测到更改时启动的命令是任意的。它可以是标准的 Linux 命令、别名、shell 函数或脚本。
安装入口
要在 Ubuntu 上安装 entr
,请使用以下命令:
sudo apt-get install entr

要在 Fedora 上安装 entr
,请键入:
sudo dnf install entr

在 Manjaro 上,命令是:
sudo pacman -Syu entr

一个简单的例子
我们将使用 touch 命令创建一个名为“example.txt”的文本文件,并告诉 entr
监控该文件。
entr
命令接受它应该通过 STDIN
监视的文件名,并接受它应该作为命令行参数运行的命令。
将文件名传递给 entr
的最简单方法是使用 ls
列出它,并将其通过管道传递给 entr
。当文件发生变化时,entr
将启动wc
命令来统计文件中的行数、字数和字符数。
/_
参数是传递给 entr
的文件的文件名的占位符。如果将一组文件传递给entr
,例如*.txt
,则/_
参数将被替换为最后一个要输入的文件变了。
touch example.txt
ls example.txt | entr wc /_

每次将更改保存到文件时,entr
都会启动 wc
。要停止 entr
,请按 q
或 Ctrl+c
。
实际用途
既然我们已经看到了 entr
的作用,并且您了解了原理,那么让我们看看一些更有用的场景。
我们将使 entr
监视当前目录中的文件。如果修改了任何文件,我们希望 entr
启动 make
以便我们重建项目。我们将链接另一个命令,make test
,以在新构建上运行一些测试。 AND 运算符 &&
只会在第一个命令完成且没有任何问题的情况下启动第二个命令。
-s
(shell) 选项确保使用的解释器是 SHELL 环境变量中定义的解释器。这确保 entr
从第一个 make
命令接收退出代码。
ls | entr -s 'make && make test'
使用 ls
命令将目录中所有文件名的列表发送到 entr
有点笨拙。目录中的文件可能是项目的一部分,但实际上并不是构建文件。也许它们是设计说明或待办事项列表。每次更改其中一个非代码文件时,您都不需要重新构建项目。
我们可以改进该命令,使其仅监视适当的源代码文件。此命令监视 C 源代码和头文件。
ls *.[ch] | entr -s 'make && make test'
当然,我们不仅限于启动 make
。您可能有一个更喜欢使用的自定义构建脚本。
ls *.[ch] | entr script.sh
利用 Git
entr
命令不是 Git 软件,但我们仍然可以使用 Git 的一些功能来简化我们的工作流程。
git ls-file
命令将列出 Git 索引和工作源代码树中的文件,同时考虑到“.gitignore”文件中定义的例外情况。这是我们感兴趣的文件的现成列表,因此让我们将其用作要监视的文件的来源。
git ls-files | entr script.sh
ls-files
命令接受命令行选项。这些可用于进一步过滤或扩充 Git 返回的文件列表:
- -c:显示缓存文件。
- -d:显示已删除的文件。
- -m:显示修改过的文件。
- -o:显示未跟踪的文件。
--exclude-standard
选项是告诉 Git 忽略与“.git/info/exclude”、本地“.gitignore”和全局“.gitignore”中的条目匹配的文件的简写方式”文件。
git ls-files -cdmo --exclude-standard | entr 'make && make test'
这会遇到很多意外情况,但无法处理正在创建的新文件。并且新文件不会在 Git 中。我们仍然可以使用一些 Bash 脚本和 entr
的功能来应对这种情况。
-d
(目录)选项使 entr
监视目录中的文件并在添加新文件时退出。通过将我们的 entr
命令包装在 while/do
循环中,整个 entr
命令行将自动重新启动,并选择新文件起来并采取行动。名称以句点“.
”开头的文件和目录将被忽略。
while true; do
{ git ls-files; git ls-files . --exclude-standard --others; } | entr -d ./script.sh
done
重启服务器和解释器
也许您使用的是解释型语言,例如 Ruby。每次更改程序文件时,都需要停止并重新启动 Ruby 解释器。您可以使用 -r
(重启)选项处理这些类型的用例。
要监视名为“hello_world.rb”的程序文件,并在每次程序文件更改时停止并重新启动 Ruby 解释器,请使用以下命令:
ls hello_world.rb | entr -r ruby hello_world.rb
每次编辑和保存程序文件时,都会重新启动 Ruby 解释器并重新加载程序。

该计划最初包含:
puts "Hello, World!"
它被编辑为:
puts "Hello, CloudSavvyIT!"
保存后,entr
重新启动 Ruby 解释器,并重新加载程序。
文件被再次编辑,添加了“读者”两个字,并保存到硬盘中。
puts "Hello, CloudSavvyIT readers!"
您可以在屏幕截图中看到三个输出。如果您按下 空格键
,entr
将重新启动命令,无论您是否更改了程序文件。
不仅仅是程序员
因为 entr
启动的命令可以是任何东西,包括 shell 脚本,所以使用 entr
来自动化进程的范围实际上是无限的。
也许您有一个目录,其中包含通过安全 FTP、rsync 或 curl 放入的文件。您可以将这些文件自动复制到其他地方,或进行压缩,或通过 grep 搜索“错误”一词。
这使它成为系统管理员和开发人员等的绝佳工具。