文件更改时如何执行命令?


434

我想要一种只要文件更改即可执行命令的快速简单的方法。我想要一个非常简单的东西,让我在终端上运行并在完成该文件处理后将其关闭。

目前,我正在使用此:

while read; do ./myfile.py ; done

然后Enter,每当我在编辑器中保存该文件时,都需要转到该终端并按。我想要的是这样的:

while sleep_until_file_has_changed myfile.py ; do ./myfile.py ; done

或任何其他简单的解决方案。

顺便说一句:我正在使用Vim,我知道我可以添加一个自动命令来在BufWrite上运行某些命令,但这不是我现在想要的解决方案。

更新:我想要一些简单的东西,如果可能的话可以丢弃。此外,我希望在终端中运行某些内容,因为我想查看程序输出(我想查看错误消息)。

关于答案:感谢您的所有答案!所有这些都非常好,并且每个人都采取了截然不同的方法。因为我只需要接受一个,所以我接受了我实际使用的一个(简单,快速且易于记忆),即使我知道它不是最优雅的。


可能的跨站点重复项:stackoverflow.com/questions/2972765/…(尽管这里是主题=))
Ciro Santilli新疆改造中心法轮功六四事件2014年

我曾在跨站点重复之前引用过它,但它被拒绝了:S;)
Francisco Tapia 2015年

4
乔纳森·哈特利(Jonathan Hartley)提出的解决方案以此处的其他解决方案为基础,并解决了投票最多的答案所面临的重大问题:缺少一些修改并且效率低下。请更改他的已接受答案,该答案也将保存在github.github.com/tartley/rerun2上(或更改为其他没有这些缺陷的解决方案)
nealmcb 2015年

Answers:


404

很简单,使用inotifywait(安装发行版的inotify-tools软件包):

while inotifywait -e close_write myfile.py; do ./myfile.py; done

要么

inotifywait -q -m -e close_write myfile.py |
while read -r filename event; do
  ./myfile.py         # or "./$filename"
done

第一个代码段比较简单,但是有一个明显的缺点:它将丢失inotifywait未运行时(尤其myfile是正在运行时)执行的更改。第二个片段没有这个缺陷。但是,请注意,它假定文件名不包含空格。如果存在问题,请使用--format选项将输出更改为不包含文件名:

inotifywait -q -m -e close_write --format %e myfile.py |
while read events; do
  ./myfile.py
done

无论哪种方式,都有一个局限性:如果某个程序替换myfile.py为另一个文件,而不是写入现有文件myfileinotifywait将会死亡。许多编辑都是以这种方式工作的。

要克服此限制,请inotifywait在目录上使用:

inotifywait -e close_write,moved_to,create -m . |
while read -r directory events filename; do
  if [ "$filename" = "myfile.py" ]; then
    ./myfile.py
  fi
done

或者,使用另一个使用相同基础功能的工具,例如incron(让您在修改文件时注册事件)或fswatch(该工具也可用于其他许多Unix变体,使用每个变体的Linux inotify类似物)。


46
我已经将所有这些内容(带有很多bash技巧)封装在一个简单易用的sleep_until_modified.sh脚本中,该脚本可以在以下位置找到:bitbucket.org/denilsonsa/small_scripts/src
DenilsonSáMaia 2010年

14
while sleep_until_modified.sh derivation.tex ; do latexmk -pdf derivation.tex ; done太棒了。谢谢。
Rhys Ulerich 2011年

5
inotifywait -e delete_self似乎对我来说效果很好。
科斯(Kos)

3
它很简单,但是有两个重要的问题:可能会丢失事件(循环中的所有事件),并且每次都完成inotifywait的初始化,这会使大型递归文件夹的解决方案变慢。
2014年

6
由于某些原因,while inotifywait -e close_write myfile.py; do ./myfile.py; done总是退出而不运行命令(bash和zsh)。为此,我需要添加|| true例如: while inotifywait -e close_write myfile.py || true; do ./myfile.py; done
ideaman42 '16

166

entrhttp://entrproject.org/)提供了一个更友好的界面来进行化(并且还支持* BSD和Mac OS X)。

它使指定多个要监视的文件(仅受限制ulimit -n)变得非常容易,消除了被替换文件的麻烦,并且所需的bash语法更少:

$ find . -name '*.py' | entr ./myfile.py

我一直在整个项目源代码树中使用它来为当前正在修改的代码运行单元测试,这已经极大地促进了我的工作流程。

-c(清除运行之间的屏幕)和-d(将新文件添加到受监视的目录时退出)这样的标志可提供更大的灵活性,例如,您可以执行以下操作:

$ while sleep 1 ; do find . -name '*.py' | entr -d ./myfile.py ; done

截至2018年初,它仍在积极开发中,可以在Debian和Ubuntu(apt install entr)中找到它; 无论如何,从作者的仓库中进行构建都是轻松的。


3
不处理新文件及其修改。
2014年

2
@Wernight-截至2014年5月7日,entr拥有新-d标志;它有点冗长,但是您可以while sleep 1 ; do find . -name '*.py' | entr -d ./myfile.py ; done处理新文件。
Paul Fenney 2014年

1
至少在debian jessie / 8.2上即可在debian仓库中获得entr ...
Peter V.Mørch2015年

5
我肯定在OS X上找到的最好的一个。fswatch捕获了太多时髦事件,我不想花时间弄清楚原因
dtc

5
值得注意的是,entr在Homebrew上可用,因此brew install entr可以按预期运行
jmarceli

108

我编写了一个Python程序来完成此操作,称为when-changed

用法很简单:

when-changed FILE COMMAND...

或观看多个文件:

when-changed FILE [FILE ...] -c COMMAND

FILE可以是目录。递归观看-r。使用%f的文件名传递给此命令。


1
@ysangkok是它,在代码:)的最新版本
[约

4
现在可以从“更改时安装pip”中获得。仍然很好。谢谢。
Al Flanagan

2
要先清除屏幕,可以使用when-changed FILE 'clear; COMMAND'
Dave James Miller

1
这个答案好得多,因为我也可以在Windows上完成。这个家伙实际上写了一个程序来得到答案。
Wolfpack'08 2015年

4
大家好消息!when-changed现在是跨平台的!查看最新的0.3.0版本:)
约翰

52

这个脚本怎么样?它使用stat命令获取文件的访问时间,并在访问时间发生更改时(无论何时访问文件)运行命令。

#!/bin/bash

### Set initial time of file
LTIME=`stat -c %Z /path/to/the/file.txt`

while true    
do
   ATIME=`stat -c %Z /path/to/the/file.txt`

   if [[ "$ATIME" != "$LTIME" ]]
   then    
       echo "RUN COMMAND"
       LTIME=$ATIME
   fi
   sleep 5
done

2
stat修改文件的时间”会更好吗?
Xen2050 '16

1
每秒运行stat多次会导致对磁盘的多次读取吗?还是fstat系统调用会以某种方式自动使这些响应高速缓存?每当我进行更改时,我都试图编写一种“ grunt watch”来编译我的c代码
Oskenso Kashi

如果您知道要预先监视的文件名,那就很好。最好将文件名传递给脚本。如果您可以传递许多文件名(例如“ mywatch * .py”),那就更好了。更好的是,如果它也可以对子目录中的文件进行递归操作,那么其他一些解决方案也可以做到。
乔纳森·哈特利

5
以防万一有人想知道大量读取,我在Ubuntu 17.04中以0.05秒的睡眠时间测试了该脚本,并 vmstat -d观察磁盘访问情况。看来linux在缓存这类事情方面做得非常出色:D
Oskenso Kashi

我正在尝试解决“ COMMAND”中的错字,但SO表示“编辑不应少于6个字符”
user337085

30

使用Vim的解决方案:

:au BufWritePost myfile.py :silent !./myfile.py

但是我不想要这种解决方案,因为键入它有点烦人,准确地记住键入的内容有点困难,并且撤消其效果(需要运行:au! BufWritePost myfile.py)也有点困难。另外,该解决方案将阻止Vim,直到命令执行完毕。

我在这里添加此解决方案只是为了完整性,因为它可能会对其他人有所帮助。

要显示程序输出(并完全破坏您的编辑流程,因为输出将覆盖编辑器几秒钟,直到您按Enter键),请删除该:silent命令。


1
结合使用entr(见下文),这可能会非常不错-只需让vim触摸entr正在监视的虚拟文件,然后让entr在后台进行其余工作...或者tmux send-keys如果您碰巧在这样的环境中:)
Paul Fenney 2014年

真好!您可以为.vimrc文件创建宏
ErichBSchulz

23

如果您刚npm安装,nodemon可能是最简单的入门方法,尤其是在OS X上,它显然没有inotify工具。当文件夹更改时,它支持运行命令。


5
但是,它仅监视.js和.coffee文件。
zelk

6
当前版本似乎支持任何命令,例如: nodemon -x "bundle exec rspec" spec/models/model_spec.rb -w app/models -w spec/models
kek

1
我希望我能获得更多信息,但是osx确实有一种跟踪更改的方法,fsevents
ConstantineK

1
在OS X上,您还可以使用带有链接的启动守护程序WatchPaths如我的链接所示。
亚当·约翰斯

19

对于那些无法inotify-tools像我一样安装的人,这应该很有用:

watch -d -t -g ls -lR

当输出更改时,该命令将退出,ls -lR并列出每个文件和目录的大小和日期,因此,如果文件被更改,则应退出该命令,如man所说:

-g, --chgexit
          Exit when the output of command changes.

我知道这个答案可能不会被任何人阅读,但我希望有人能找到它。

命令行示例:

~ $ cd /tmp
~ $ watch -d -t -g ls -lR && echo "1,2,3"

打开另一个终端:

~ $ echo "testing" > /tmp/test

现在第一个终端将输出 1,2,3

简单的脚本示例:

#!/bin/bash
DIR_TO_WATCH=${1}
COMMAND=${2}

watch -d -t -g ls -lR ${DIR_TO_WATCH} && ${COMMAND}

5
不错的技巧。我进行了测试,当列表很长且更改的文件不在屏幕上时,似乎出现了问题。一个小的修改可能是这样的: watch -d -t -g "ls -lR tmp | sha1sum"
Atle 2016年

3
如果您每秒观看一次解决方案,它将永远有效并且仅在某些文件更改后运行MY_COMMAND:watch -n1“ watch -d -t -g ls -lR && MY_COMMAND”
mnesarco

我的手表版本(在Linux上watch from procps-ng 3.3.10)在其间隔内接受浮动秒,因此watch -n0.2 ...将每五分之一秒轮询一次。适合那些健康的亚毫秒级单位测试。
乔纳森·哈特利

15

rerun2在github上)是一个10行的Bash脚本,其形式为:

#!/usr/bin/env bash

function execute() {
    clear
    echo "$@"
    eval "$@"
}

execute "$@"

inotifywait --quiet --recursive --monitor --event modify --format "%w%f" . \
| while read change; do
    execute "$@"
done

将github版本保存为PATH中的“重新运行”,并使用以下命令调用它:

rerun COMMAND

每当当前目录中存在一个文件系统修改事件时,它将运行COMMAND(递归)。

人们可能会喜欢的事情:

  • 它使用inotify,因此比轮询更具响应性。每次单击“保存”时,都可运行亚毫秒级单元测试或渲染graphviz点文件。
  • 因为它是如此之快,所以您不必为了性能原因而告诉它忽略大的子目录(例如node_modules)。
  • 它具有超级响应能力,因为它在启动时仅调用inotifywait一次,而不是运行它,并且每次迭代都需要花费大量时间来建立手表。
  • 只是Bash的12行
  • 因为它是Bash,它会解释您传递的命令,就像您在Bash提示符下键入命令一样。(如果使用其他外壳,那么这可能不太酷。)
  • 它不会丢失在执行COMMAND时发生的事件,这与本页上的其他大多数inotify解决方案不同。
  • 在第一个事件上,它将进入0.15秒的“死区”,在此期间,其他事件将被忽略,而COMMAND只运行一次。这样一来,由Vi或Emacs在保存缓冲区时执行的create-write-move舞动所引起的一系列事件不会导致可能缓慢运行的测试套件的多次繁琐执行。在执行COMMAND期间发生的任何事件都不会被忽略-它们将导致第二个死周期并随后执行。

可能有人对此不满意:

  • 它使用inotify,因此在Linuxland之外无法使用。
  • 因为它使用inotify,所以它会阻止尝试监视包含比用户inotify监视的最大数量更多的文件的目录。默认情况下,在我使用的不同计算机上,此值似乎设置为5,000至8,000,但很容易增加。参见https://unix.stackexchange.com/questions/13751/kernel-inotify-watch-limit-reached
  • 它无法执行包含Bash别名的命令。我可以保证这曾经奏效。原则上,因为这是Bash,而不是在子shell中执行COMMAND,所以我希望它能起作用。如果有人知道为什么不知道,我很想听听。此页面上的许多其他解决方案也无法执行此类命令。
  • 我个人希望我能够在正在运行的终端上敲一个键,以手动导致额外执行COMMAND。我可以简单地添加一下吗?并发运行的“ while read -n1”循环还调用execute?
  • 现在,我已经对其进行了编码,以清除终端并在每次迭代中打印执行的COMMAND。有些人可能想添加命令行标志来关闭诸如此类的功能,但这会增加很多大小和复杂性。

这是@cychoi的anwer的改进。


2
我相信您应该使用"$@"而不是$@,以便正确处理包含空格的参数。但是同时使用eval,这会迫使重新运行的用户在引用时要格外小心。
DenilsonSáMaia 2015年

谢谢丹尼尔森。您能否举一个需要仔细报价的例子?我在过去的24小时内一直在使用它,到目前为止,还没有发现空格有任何问题,也没有仔细引用任何内容-只是将其称为rerun 'command'。您是否只是在说,如果我使用“ $ @”,那么用户可以调用as rerun command(不带引号?)对我来说似乎没有什么用:我通常不希望Bash 在传递命令之前对其进行任何处理重新运行。例如,如果命令包含“ echo $ myvar”,那么我将希望在每次迭代中查看myvar的新值。
乔纳森·哈特利

1
喜欢的东西rerun foo "Some File"可能会中断。但是由于您正在使用eval,因此可以将其重写为rerun 'foo "Some File"。请注意,有时路径扩展可能会引入空格:rerun touch *.foo可能会中断,并且使用的rerun 'touch *.foo'语义会稍有不同(路径扩展仅发生一次或多次)。
DenilsonSáMaia 2015年

谢谢您的帮助。是的:rerun ls "some file"由于空格而中断。rerun touch *.foo*通常可以正常工作,但是如果与* .foo匹配的文件名包含空格,则会失败。感谢您帮助我了解rerun 'touch *.foo'语义的不同,但是我怀疑单引号的版本是我想要的语义:我希望每次重新运行都像重新键入命令一样起作用-因此,我希望 *.foo在每次迭代中进行扩展。我将尝试您的建议以检查它们的影响...
Jonathan Hartley

有关此PR的更多讨论(github.com/tartley/rerun2/pull/1)及其他。
乔纳森·哈特利

12

这是一个简单的shell Bourne shell脚本,它:

  1. 带有两个参数:要监视的文件和一个命令(如有必要,带有参数)
  2. 将您正在监视的文件复制到/ tmp目录
  3. 每两秒钟检查一次,查看所监视的文件是否比副本新
  4. 如果是较新的版本,它将用较新的原始版本覆盖副本并执行命令
  5. 当您按Ctr-C时会自动清理

    #!/bin/sh  
    f=$1  
    shift  
    cmd=$*  
    tmpf="`mktemp /tmp/onchange.XXXXX`"  
    cp "$f" "$tmpf"  
    trap "rm $tmpf; exit 1" 2  
    while : ; do  
        if [ "$f" -nt "$tmpf" ]; then  
            cp "$f" "$tmpf"  
            $cmd  
        fi  
        sleep 2  
    done  
    

这适用于FreeBSD。我能想到的唯一可移植性问题是,如果其他一些Unix没有mktemp(1)命令,但是在那种情况下,您可以对临时文件名进行硬编码。


9
轮询是唯一可移植的方法,但是大多数系统具有文件更改通知机制(在Linux上为intify,在FreeBSD上为kqueue,...)。这样做时$cmd,您会遇到一个严重的引用问题,但是幸运的是,该问题很容易解决:抛弃cmd变量并执行"$@"。您的脚本不适合监视大文件,但是可以通过替换cptouch -r(您只需要日期,而不是内容)来解决。在可移植性方面,该-nt测试需要bash,ksh或zsh。
吉尔斯


6

使用NodeJ的另一个解决方案fsmonitor

  1. 安装

    sudo npm install -g fsmonitor
    
  2. 从命令行(例如,监视日志和“零售”(如果一个日志文件更改))

    fsmonitor -s -p '+*.log' sh -c "clear; tail -q *.log"
    

旁注:tail -F -q *.log我认为示例可以解决。
Volker Siegel

这只是一个例子,tail -f不是clear终端。
Atika


6

如果已安装nodemon,则可以执行以下操作:

nodemon -w <watch directory> -x "<shell command>" -e ".html"

就我而言,我在本地编辑html并在文件更改时将其发送到我的远程服务器。

nodemon -w <watch directory> -x "scp filename jaym@jay-remote.com:/var/www" -e ".html"

6

在Linux下:

man watch

watch -n 2 your_command_to_run

将每2秒运行一次命令。

如果您的命令需要2秒钟以上的时间运行,那么watch会一直等到完成后再执行。


这很简单,尽管有些浪费,但是对于开发任务(例如实时更改样式)很容易。
Xeoncross

2
如果命令运行超过两秒钟会发生什么?
2015年

@thirtythreeforty在Ubuntu上进行的一项快速实验表明,无论命令运行多长时间,手表都会等待整整两秒钟。FWIW,可以用“ -n”指定睡眠时间,最短为0.1秒。
乔纳森·哈特利

5

看门狗是一个Python项目,可能正是您要寻找的东西:

支持平台

  • Linux 2.6(inotify)
  • Mac OS X(FSEvents,kqueue)
  • FreeBSD / BSD(kqueue)
  • Windows(具有I / O完成端口的ReadDirectoryChangesW; ReadDirectoryChangesW工作线程)
  • 与操作系统无关(轮询磁盘以获取目录快照并定期比较它们;速度慢,不建议使用)

刚刚为其编写了一个命令行包装器watchdog_exec

运行示例

在涉及当前目录中文件和文件夹的fs事件上,运行echo $src $dst命令,除非已修改fs事件,然后运行python $src命令。

python -m watchdog_exec . --execute echo --modified python

使用短参数,并限制仅在事件涉及“ main .py” 时执行:

python -m watchdog_exec . -e echo -a echo -s __main__.py

编辑:刚发现Watchdog有一个名为的正式CLI watchmedo,所以也请检查一下。


4

如果您的程序生成某种日志/输出,则可以创建一个Makefile,该文件的规则取决于您的脚本,并执行如下操作:

while true; do make -s my_target; sleep 1; done

或者,您可以创建一个伪音目标并为其设置规则,既调用脚本又触摸伪音目标(同时仍取决于脚本)。


11
while sleep 1 ; do something ; done比稍好while true ; do something ; sleep 1 ; done。至少在按Ctrl + C时可以轻松停止。
丹尼尔森·萨迈亚

消除睡眠会导致繁忙的循环(CPU发热并损害笔记本电脑的电池寿命)吗?
史蒂文·卢

2
@StevenLu:不,睡眠不是忙碌的等待。问题是,如果睡眠在体内,Control-C将终止睡眠,循环将重新开始。启动循环的功耗很小。在终端机中尝试一下。如果您体内有睡眠,则需要按住Control-C才能正常工作。
Janus Troelsen,2012年

对。我想我错过了,没有看到睡眠仍然是循环条件。这个小调整非常棒。
史蒂文·卢

4

2
这是一个功能丰富的200行Bash脚本,stat该脚本会轮询给定的文件名,md5sum在输出中运行 ,并在此值更改时重新运行给定的命令。因为它是Bash,所以我怀疑它可以很好地运行给定命令,就像在Bash提示符下键入命令一样。(相比之下,此处用其他语言编写的大多数解决方案将无法执行包含诸如shell别名之类的命令,例如ll
Jonathan Hartley

4

改进了吉尔斯的答案

此版本运行inotifywait一次,然后监视事件(例如:)modify。这样inotifywait 不必在遇到每个事件时都重新执行。

快又快!(即使以递归方式监视大目录)

inotifywait --quiet --monitor --event modify FILE | while read; do
    # trim the trailing space from inotifywait output
    REPLY=${REPLY% }
    filename=${REPLY%% *}
    # do whatever you want with the $filename
done

对于仅Linux用户,这是页面上的最佳答案。用“ execute $ @”替换循环中的内容,用户可以调用此脚本并传递自己的命令来运行。如果使用它,它甚至可以与包含外壳别名的命令一起使用,例如使用“。scriptname COMMAND”之类的东西。这样仍会在PATH上找到脚本名。
乔纳森·哈特利

我认为您是说要在“阅读时回复”旁边输入?
乔纳森·哈特利

1
感谢您的澄清。谢谢你的分阶段!我会删除这些评论,但现在当然不会。
乔纳森·哈特利

3

在编程方面要多一点,但是您需要像inotify这样的东西。有许多语言的实现,例如jnotifypyinotify

该库允许您监视单个文件或整个目录,并在发现操作时返回事件。返回的信息包括文件名,操作(创建,修改,重命名,删除)和文件路径以及其他有用信息。


3

对于那些正在寻找FreeBSD解决方案的人,这里是端口:

/usr/ports/sysutils/wait_on

3

我喜欢它的简单性,while inotifywait ...; do ...; done但是它有两个问题:

  • 遗失期间发生的档案变更do ...;将会遗失
  • 在递归模式下使用时速度

因此,我制作了一个使用inotifywait的帮助程序脚本,没有这些限制:inotifyexec

我建议您将此脚本放在路径中,例如中的~/bin/。仅通过运行命令来描述用法。

例: inotifyexec "echo test" -r .


更新了脚本以支持正则表达式模式匹配。
2014年

通过在“ --monitor”模式下使用inotifywait可以解决这两个问题。请参阅cychoi的答案。
乔纳森·哈特利

3

使用命令改进了塞巴斯蒂安的解决方案watch

watch_cmd.sh

#!/bin/bash
WATCH_COMMAND=${1}
COMMAND=${2}

while true; do
  watch -d -g "${WATCH_COMMAND}"
  ${COMMAND}
  sleep 1     # to allow break script by Ctrl+c
done

通话示例:

watch_cmd.sh "ls -lR /etc/nginx | grep .conf$" "sudo service nginx reload"

它可以工作,但要小心:watch命令具有已知的错误(请参阅man):它仅对-g CMD输出终端部分中可见的更改作出反应。


2

您可以尝试反射

Reflex是一个监视目录并在某些文件更改时重新运行命令的小工具。这对于自动运行编译/皮棉/测试任务以及在代码更改时重新加载应用程序非常有用。

# Rerun make whenever a .c file changes
reflex -r '\.c$' make

您能否引用/解释一下该工具?快速阅读有关如何推荐软件的指南。
bertieb

1

我用来跟踪文件更改的oneliner答案:

$ while true ; do NX=`stat -c %Z file` ; [[ $BF != $NX ]] && date >> ~/tmp/fchg && BF=$NX || sleep 2 ; done

如果您知道第一个日期是开始时间,则无需初始化BF。

这是简单且可移植的。使用脚本在同一策略下还有另一个答案。也看一看。


用法:我正在用它来调试并关注~/.kde/share/config/plasma-desktop-appletsrc;由于某种未知的原因而使我失去了SwitchTabsOnHover=false


1

我用这个脚本来做。我在监视器模式下使用inotify

#!/bin/bash
MONDIR=$(dirname $1)
ARQ=$(basename $1)

inotifywait -mr -e close_write $MONDIR | while read base event file 
do
  if (echo $file |grep -i "$ARQ") ; then
    $1
  fi
done

将其另存为runatwrite.sh

Usage: runatwrite.sh myfile.sh

它将在每次写入时运行myfile.sh。


1

对于使用OS X的用户,可以使用LaunchAgent监视路径/文件中的更改,并在发生更改时执行某些操作。仅供参考-LaunchControl是一款易于制作/修改/删除守护程序/代理的好应用。

示例取自此处

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN
http://www.apple.com/DTDs/PropertyList-1.0.dtd>
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>test</string>
    <key>ProgramArguments</key>
    <array>
        <string>say</string>
        <string>yy</string>
    </array>
    <key>WatchPaths</key>
    <array>
        <string>~/Desktop/</string>
    </array>
</dict>
</plist>


0

对于通过谷歌搜索特定文件的更改发现此问题的人,答案要简单得多(受Gilles的回答启发)。

如果要在写入特定文件执行某些操作,请按以下步骤操作:

while true; do
  inotifywait -e modify /path/to/file
  # Do something *after* a write occurs, e.g. copy the file
  /bin/cp /path/to/file /new/path
done

例如,copy_myfile.sh将其另存为,然后将.sh文件放入/etc/init.d/文件夹以使其在启动时运行。


与Giles的答案共享一个问题,后者在每次迭代中都运行inotifywait,对于递归地查看非常大的目录可能没有响应。请参见cychoi的答案以解决此问题。
乔纳森·哈特利


0

正如其他一些人所做的那样,我还编写了一个轻量级的命令行工具来执行此操作。它已完全记录,测试和模块化。

看做

安装

您可以使用以下命令安装(如果您拥有Python3和pip):

pip3 install git+https://github.com/vimist/watch-do

用法

通过运行立即使用它:

watch-do -w my_file -d 'echo %f changed'

功能概述

  • 支持文件遍历(使用-w '*.py'-w '**/*.py'
  • 在文件更改时运行多个命令(只需-d再次指定标志)
  • 动态维护文件列表,以查看是否使用了globbing(-r将其启用)
  • “监视”文件的多种方法:
    • 修改时间(默认)
    • 文件哈希
    • 轻松实现自己的功能(这是ModificationTime监视程序)
  • 模块化设计。如果要运行命令,则在访问文件时,编写自己的观察程序很简单(确定是否应运行执行程序的机制)。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.