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

当前,我正在使用此文件:

while read; do ./myfile.py ; done


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

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


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

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

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

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

评论

可能的跨站点重复项:stackoverflow.com/questions/2972765/…(尽管这里是topic =))

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

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

#1 楼

使用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的每个变体)。

评论


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

– DenilsonSáMaia
2010年8月30日,0:57

而sleep_until_modified.sh derivation.tex;做latexmk -pdf derivation.tex;做的太棒了。谢谢。

– Rhys Ulerich
2011-12-15在16:49



inotifywait -e delete_self对我来说似乎很好。

–科斯
13年10月1日在11:29

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

–晚上
14年4月29日在13:00

由于某些原因,在inotifywait中-e close_write myfile.py;做./myfile.py; done总是在不运行命令(bash和zsh)的情况下退出。为此,我需要添加||。正确,例如:while inotifywait -e close_write myfile.py ||真正;做./myfile.py;完成

–ideasman42
16年8月3日在23:36



#2 楼

entr(http://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)中可以找到;无论如何,从作者的回购库中进行构建都是轻松的。

评论


不处理新文件及其修改。

–晚上
2014年4月29日在12:58

@Wernight-自2014年5月7日起,entr具有新的-d标志;它稍微有点long,但您可以在睡觉时做1;确实找到。名称'* .py'| entr -d ./myfile.py;处理新文件。

– Paul Fenney
2014年5月23日8:27



至少在debian jessie / 8.2上,entr也可以在debian仓库中使用...

– Peter V.Mørch
2015年10月18日在21:59

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

–dtc
16年2月6日在20:35

值得注意的是,Homebrew上提供了entr,因此brew install entr将按预期工作

– jmarceli
17年12月14日在15:42

#3 楼

我编写了一个Python程序来执行此操作,即称为更改时。

用法很简单:

when-changed FILE COMMAND...


或观看多个文件:

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


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

评论


@ysangkok是的,在最新版本的代码中:)

–乔
2012年10月11日16:35

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

– A. L. Flanagan
15年1月8日在18:37

要首先清除屏幕,可以使用何时更改FILE'clear;命令'。

–戴夫·詹姆斯·米勒(Dave James Miller)
15年2月14日在9:29

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

–Wolfpack'08
15年5月13日在15:33



大家好消息!何时更改现在是跨平台的!查看最新的0.3.0版本:)

–乔
16年1月23日在2:41

#4 楼

这个脚本怎么样?它使用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
 


评论


指出修改时间不是“文件更改时”更好的答案吗?

– Xen2050
16-2-27在16:42

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

–奥肯索·喀什(Oskenso Kashi)
16 Dec 7'在18:01

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

–乔纳森·哈特利
17年2月16日在14:18

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

–奥肯索·喀什(Oskenso Kashi)
17年8月2日,0:01

我正在尝试解决“ COMMAND”中的错字,但S.O.说“编辑不应少于6个字符”

–user337085
18年5月1日在18:58

#5 楼

使用Vim的解决方案:

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


但是我不想要这种解决方案,因为它有点烦人,很难记住确切的类型,而且撤消其影响有点困难(需要运行:au! BufWritePost myfile.py)。此外,该解决方案会阻塞Vim,直到命令执行完毕。

我在此处添加此解决方案只是出于完整性的考虑,因为它可能会对其他人有所帮助。

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

评论


与entr结合使用时,这可能会非常不错(请参见下文)-只需使vim触摸entr正在监视的虚拟文件,然后让entr在后台进行其余工作...或tmux send-key(如果碰巧在这种情况下)一个环境 :)

– Paul Fenney
2014年5月23日在8:42

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

– ErichBSchulz
18-3-19的1:49

#6 楼

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

watch -d -t -g ls -lR

当输出更改时,此命令将退出,ls -lR将列出每个文件和目录,它的大小和日期,因此,如果文件被更改,则应退出命令,就像男人说的那样:

-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=
COMMAND=

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


评论


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

– Atle
16 Dec 16 '14:10



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

–mnesarco
17年7月23日在2:26

我的watch版本(在Linux上,来自procps-ng 3.3.10的watch)在其间隔内接受float秒,因此watch -n0.2 ...将每五分之二轮询一次。适合那些健康的亚毫秒级单位测试。

–乔纳森·哈特利
18年4月19日在16:23



但是,这似乎并没有陷入循环,并在第一次迭代后结束

– FantomX1
11月4日22:08

#7 楼

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

评论


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

–zelk
2012年7月20日在10:27

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

–kek
2013年10月10日15:15



我希望我有更多的信息,但是osx确实有一种方法来跟踪更改,fsevents

–ConstantineK
2014年10月7日在4:34

在OS X上,您也可以使用带有WatchPaths键的Launch Daemons,如我的链接所示。

–亚当·约翰斯(Adam Johns)
2014年11月16日23:48

#8 楼

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一次,而不是运行它,并且每次迭代都导致建立手表的代价很高。
它只有12行Bash
,因为它是Bash,它会解释您传递的命令,就像在Bash提示符下键入命令一样。 (如果使用其他shell,这大概不太酷。)
不会丢失在执行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的改进。 >

评论


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

– DenilsonSáMaia
2015年9月10日15:20

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

–乔纳森·哈特利
2015年9月11日17:53



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

– DenilsonSáMaia
2015年9月11日在23:07

谢谢您的帮助。是的:由于空格,重新运行ls“ some file”中断。重新运行touch * .foo *通常可以正常工作,但是如果与* .foo匹配的文件名包含空格,则失败。感谢您帮助我查看重新运行'touch * .foo'的语义如何,但是我怀疑单引号的版本是我想要的语义:我希望每次重新运行的迭代都像我再次键入命令一样-因此我希望在每次迭代中扩展* .foo。我将尝试您的建议以检查其效果...

–乔纳森·哈特利
2015年9月12日下午5:52



有关此PR的更多讨论(github.com/tartley/rerun2/pull/1)及其他。

–乔纳森·哈特利
2015年9月12日下午6:09

#9 楼

这是一个简单的shell Bourne shell脚本,它包含以下内容:


带有两个参数:要监视的文件和一个命令(如有必要,带有参数)
复制要监视的文件到/ tmp目录中
每两秒钟检查一次,查看所监视的文件是否比副本要新
,如果它是较新的,它将用较新的原件覆盖副本并执行命令

按下Ctr-C后会自动清理

#!/bin/sh  
f=  
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)命令,但是在那种情况下,您可以对临时文件名进行硬编码。

评论


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

–吉尔斯'所以-不再是邪恶的'
2010年8月27日在22:22

#10 楼

如果您已安装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"


#11 楼

看看incron。它与cron类似,但是使用inotify事件而不是时间。

评论


可以做到这一点,但是与该页面上的其他解决方案相比,创建incron条目是一个非常费力的过程。

–乔纳森·哈特利
2015年9月9日在20:37

#12 楼

使用NodeJ的另一种解决方案fsmonitor:




从命令行安装

sudo npm install -g fsmonitor



从命令行(示例,监视日志和“零售”(如果一个日志文件发生了更改)

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




评论


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

– Volker Siegel
15年4月18日在1:39

仅举一个例子,tail -f不会清除终端。

– Atika
19年2月11日在15:45

#13 楼

查看Guard,尤其是使用此插件:

https://github.com/hawx/guard-shell

您可以将其设置为观看任意数量的模式在项目目录中,并在发生更改时执行命令。即使有一个插件,您也有机会尝试一下。

#14 楼

在Linux下:

man watch

watch -n 2 your_command_to_run


每2秒钟运行一次命令。

如果您的命令运行超过2秒钟,则手表将等待直到完成,然后再做一次。

评论


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

– Xeoncross
14年7月15日在18:32

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

–三十三十四
15年2月24日在6:53

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

–乔纳森·哈特利
2015年9月9日在20:36

这不会回答问题,而是运行程序期刊。

–dirdir
19年1月1日在12:49

#15 楼

Watchdog是一个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,所以也请检查一下。

#16 楼

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

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


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

评论


睡眠1;做点什么 ;做比真实情况要好一些;做点什么 ;睡觉1;完成。至少在按Ctrl + C时可以轻松停止。

– DenilsonSáMaia
10年8月28日在4:59



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

–陆even
2012年7月12日在4:52



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

– Janus Troelsen
2012年9月19日上午11:25

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

–陆even
2012-09-19 17:55



#17 楼

swarminglogic编写了一个名为watchfile.sh的脚本,也可以作为GitHub Gist使用。

评论


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

–乔纳森·哈特利
2015年9月9日在20:30



#18 楼

改进了Gilles的回答。

此版本一次运行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上找到脚本名。

–乔纳森·哈特利
2015年9月9日21:00

我想您是说要在“阅读时回复”的同时写?

–乔纳森·哈特利
2015年9月9日21:00

感谢您的澄清。谢谢你的分阶段!我会删除这些评论,但现在当然不会。

–乔纳森·哈特利
15年9月30日在11:25

#19 楼

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

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

#20 楼

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

/usr/ports/sysutils/wait_on


#21 楼

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


do ...;期间发生的文件更改将丢失


以递归方式使用时速度较慢模式

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

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

示例:inotifyexec "echo test" -r .

评论


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

–晚上
14-10-21在12:56

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

–乔纳森·哈特利
2015年9月9日在20:01



#22 楼

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

watch_cmd.sh

#!/bin/bash
WATCH_COMMAND=
COMMAND=

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输出的端子部分中的VISIBLE做出反应。

#23 楼

您可以尝试使用reflex。

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

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


评论


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

–bertieb
17 Mar 1 '17 at 20:38



#24 楼

我用来跟踪文件更改的一个单线答案:

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


如果您知道第一个日期是开始时间。

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



用法:我正在使用它进行调试并密切注意~/.kde/share/config/plasma-desktop-appletsrc;由于某些未知原因而使我失去了SwitchTabsOnHover=false

#25 楼

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

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

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


将其另存为runatwrite.sh

Usage: runatwrite.sh myfile.sh


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


#26 楼

对于使用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>


#27 楼

我有一个GIST,用法非常简单

watchfiles <cmd> <paths...>


https://gist.github.com/thiagoh/5d8f53bfb64985b94e5bc8b3844dba55

#28 楼

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

Watch-Do

安装

您可以使用以下命令进行安装(如果您拥有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标志)
动态维护列表要使用文件监视的文件数量(请参见-r启用此功能)
“监视”文件的多种方法:


修改时间(默认)
文件hash
尝试自行实现(这是ModificationTime监视程序)


模块化设计。如果要运行命令,则在访问文件时,编写您自己的观察程序很简单(确定是否应运行doers的机制)。


评论


我最喜欢的答案!

–颜恩VR
19年11月7日在22:24

#29 楼

我编写了一个名为rerun的Python程序来执行此操作。

UPDATE:该答案是一个Python脚本,用于轮询更改,这在某些情况下很有用。对于使用inotify的仅限Linux的Bash脚本,请参见我的其他答案,在此页面上搜索“ rerun2”。

使用以下命令安装Python2或Python3:

pip install --user rerun


,用法非常简单:

rerun "COMMAND"


该命令应作为单个arg而不是以空格分隔的arg序列。因此,如图所示将其引用,这样可以减少您必须添加的其他转义字符。只需键入命令即可,就像在命令行中键入命令一样,但是用引号引起来。

默认情况下,它监视当前目录中或目录下的所有文件,而跳过诸如已知源代码管理目录dir之类的内容。 git,.svn等。

可选标志包括'-i NAME',它忽略对命名文件或目录的更改。这可以多次给出。

由于它是Python脚本,因此需要将命令作为子进程运行,并且我们使用用户当前shell的新实例来解释“ COMMAND”并决定要实际运行的进程。但是,如果您的命令包含.bashrc中定义的shell别名等,则子shell不会加载这些别名。为了解决这个问题,您可以给rerun一个'-I'标志,以使用交互式(也称为'login')子外壳。与启动常规shell相比,它更慢且更容易出错,因为它必须提供您的.bashrc。

我在Python 3中使用它,但是最后我检查了rerun仍然可以在Python 2中使用。 br />
双刃剑是它使用轮询而不是inotify。从好的方面来说,这意味着它可以在所有操作系统上运行。另外,相对于此处显示的某些其他解决方案,它只对文件系统进行一次更改就运行给定命令,而不是对每个修改过的文件运行一次,这比在此显示的某些其他解决方案要好,而如果任何文件再次更改,则它确实会再次运行该命令在命令运行时。

不利的一面是,轮询意味着存在0.0到1.0秒的延迟,当然,监视非常大的目录会很慢。话虽如此,但是我从来没有遇到过一个足够大的项目,只要您使用'-i'来忽略诸如virtualenv和node_modules之类的大问题,就不会引起人们的注意。

Hmmm。 rerun多年来对我一直是必不可少的-我基本上每天使用它八个小时来运行测试,在编辑它们时重建点文件等。但是现在我要在这里键入它,很明显,我需要切换到使用inotify的解决方案(我不再使用Windows或OSX。)并以Bash编写(因此它可以与别名一起使用,而不会产生任何麻烦。)

评论


这个答案远不如我的其他答案(rerun2)

–乔纳森·哈特利
2015年9月9日在21:50

从我在2020年针对Mac OS X尝试的所有解决方案中,重新运行为在任何项目(例如Elixir,Python等)上运行make测试提供了最佳结果。$ pip3 install rerun $重新运行--verbose --ignore = _build- -ignore = deps“使测试单元”

–弗拉基米尔(Vladimir Vukanac)
2月25日20:31



#30 楼

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

如果要在写入特定文件后执行某些操作,请方法:

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的答案以解决此问题。

–乔纳森·哈特利
2015年9月9日19:51