在Mac上是否有“ watch”或“ inotifywait”之类的命令?


287

我想在Mac(雪豹)上观看一个文件夹,然后执行一个脚本(为它提供刚移入文件夹的文件名(作为参数... x.sh“文件名”))。

我有一个全部用bash(x.sh)编写的脚本,它将在输入$ 1上移动一些文件和其他内容。当新文件/文件夹移动/创建到目录中时,我只需要OSX给我文件名。

有这样的命令吗?


1
您应该问问DropBox是如何做到的,因为大概他们尝试了所有可用的选项。
杰夫·伯奇斯

2
@JeffBurdges我不确定这是一件容易的事。但是我会说,在浏览了苹果的FSEvents Reference之后,如果Dropbox不使用它真的很愚蠢。该fswatchUTIL呈现为答案其实使用这种方法,下面做。
史蒂文·卢

Answers:


446

fswatch

fswatch是一个使用Mac OS X FSEvents API监视目录的小程序。收到有关对该目录进行任何更改的事件时,将由以下命令执行指定的shell命令:/bin/bash

如果您使用的是GNU / Linux,则 inotifywatchinotify-tools大多数发行版的软件包的一部分 )提供了类似的功能。

更新: fswatch现在可以在包括BSD,Debian和Windows在内的许多平台上使用。

语法/一个简单的例子

可以监视多个路径的新方法-对于1.x及更高版本

fswatch -o ~/path/to/watch | xargs -n1 -I{} ~/script/to/run/when/files/change.sh

注意:如果不是,则输出的数字by -o将添加到xargs命令末尾-I{}。如果确实选择使用该数字,请{}在命令中放置任何位置。

版本0.x的旧方法:

fswatch ~/path/to/watch ~/script/to/run/when/files/change.sh

使用自制软件安装

截至13年9月12日,它已重新添加到自制软件中 -是的!因此,更新您的公式列表(brew update),然后您需要做的就是:

brew install fswatch

无自制安装

在以下命令中键入这些命令 Terminal.app

cd /tmp
git clone https://github.com/alandipert/fswatch
cd fswatch/
make
cp fswatch /usr/local/bin/fswatch

如果您c的系统上没有编译器,则可能需要安装Xcode或Xcode命令行工具-两者都是免费的。但是,在这种情况下,您可能应该只检查homebrew

fswatch版本1.x的其他选项

Usage:
fswatch [OPTION] ... path ...

Options:
 -0, --print0          Use the ASCII NUL character (0) as line separator.
 -1, --one-event       Exit fsw after the first set of events is received.
 -e, --exclude=REGEX   Exclude paths matching REGEX.
 -E, --extended        Use exended regular expressions.
 -f, --format-time     Print the event time using the specified format.
 -h, --help            Show this message.
 -i, --insensitive     Use case insensitive regular expressions.
 -k, --kqueue          Use the kqueue monitor.
 -l, --latency=DOUBLE  Set the latency.
 -L, --follow-links    Follow symbolic links.
 -n, --numeric         Print a numeric event mask.
 -o, --one-per-batch   Print a single message with the number of change events.
                       in the current batch.
 -p, --poll            Use the poll monitor.
 -r, --recursive       Recurse subdirectories.
 -t, --timestamp       Print the event timestamp.
 -u, --utc-time        Print the event time as UTC time.
 -v, --verbose         Print verbose output.
 -x, --event-flags     Print the event flags.

See the man page for more information.

您的说明或没有自制程序的安装似乎不再起作用。make引发关于找不到makefile的错误。幸运的是sudo port install fswatch,对于使用MacPorts而非Homebrew的我们这些人来说,fswatch现在可以在MacPorts上运行。
coredumperror

如果您使用带有静态参数的命令(例如,我正在src上运行单元测试并进行测试更改),那么这可能对您不起作用。这个问题(stackoverflow.com/questions/25689589/…)是我需要的第二部分。
jskulski

4
我在那里听到你的声音:fswatch ./ | xargs -I{} cp {} ~/Dropbox/backup/latest/
fionbio '16

fswatch比诸如entr或when_changed之类的工具要好,后者在处理.git目录时存在一些错误。fswatch更专业。简单来说,您fswatch .将监视当前目录。
匿名

我建议fswatch -0 -v -o /path/to/watched/files | xargs -0 -n 1 -I {} [your command]使用-0NULL。此代码对我
有用

95

您可以使用的launchd用于这一目的。可以将“已启动”配置为在修改文件路径时自动启动程序。

例如,/usr/bin/logger当修改我的用户帐户的桌面文件夹时,以下启动的配置plist将启动程序:

<?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>logger</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/logger</string>
        <string>path modified</string>
    </array>
    <key>WatchPaths</key>
    <array>
        <string>/Users/sakra/Desktop/</string>
    </array>
</dict>
</plist>

要激活配置plist,请将其另存为“ logger.plist”到“库”文件夹中的LaunchAgents文件夹中。

然后,可以从外壳程序使用以下命令通过以下命令launchctl激活logger.plist:

$ launchctl load ~/Library/LaunchAgents/logger.plist

现在正在监视桌面文件夹。每次更改时,您都应该在system.log中看到一个输出(使用Console.app)。要停用logger.plist,请运行:

$ launchctl unload ~/Library/LaunchAgents/logger.plist

上面的配置文件使用该WatchPaths选项。或者,您也可以使用该 QueueDirectories选项。有关更多信息,请参见启动的手册页。


1
有没有办法让它监视文件内容以及文件路径的变化?
2012年

2
我不这么认为。您可以为此使用opensnoop
sakra 2012年

1
我可以使用它,但是当我切换/usr/bin/logger我的Bash脚本并删除"<string>path modified</strong>"条目时,我找不到任何方式让我的bash脚本知道桌面上的哪个文件已被修改-只是该事件发生了。我尝试查看$0,但$1仅获得脚本名称本身,并注意到传递给它。
Volomike

另外,这个东西一旦检测到变化是否会进入循环,而不是在检测到变化时才启动(和停止)?我希望它按需运行,而不是一直循环运行,告诉我,例如,两天前,我的桌面发生了一些变化,一遍又一遍地写在日志中。那么,我们是否需要在此plist中使用某种间隔选项?
Volomike

伟大的工作和解释
ChenSmile

37

可以通过Homebrew获得的Facebook 守望者看起来也不错。它还支持过滤:

这两行在源目录上建立了一个监视,然后设置了一个名为“ buildme”的触发器,该触发器将在更改CSS文件时运行名为“ minify-css”的工具。该工具将传递一个已更改文件名的列表。

$ watchman watch ~/src

$ watchman -- trigger ~/src buildme '*.css' -- minify-css

请注意,该路径必须是绝对路径。


1
到目前为止,这是最好的工具。
BentOnCoding

1
这是一个非常不错的小程序:文档很棒,它不会打开无限循环(fswatch似乎可以做到),并且它会记住您在重新启动后创建的手表并自动重新启动它们。
布拉德,

21

您可能想看一看(也许扩展)我的小工具kqwait。目前,它只是闲坐着等待一个文件的写事件,但是kqueue体系结构允许分层事件堆栈。


到目前为止在山狮上工作。非常好!
斯科特

所以这真的很棒。我遇到了一个小问题fswatch(这也很好,因为它的包装很轻,也可以修改以做我确定的正确事情)在运行类似git status(它每次zsh都会运行)时触发提示在我的计算机上呈现...)实际上,它通过创建一个无限的反馈循环来弄糟我拥有的这个精心编写的脚本。但是,kqwait提供有关已更改文件的信息,并且不会被绊倒git status。我确实需要它在写入时触发。
史蒂文·卢

2
$ brew install kqwait && while true; do kqwait doc/my_file.md; make; done
约书亚·库克

15

看门狗是用于监视文件/目录的跨平台python API,它具有内置的“技巧”工具,可让您在事件(包括新添加的文件,删除的文件和更改的文件)发生时触发操作(包括shell命令)。


7

这只是提到entr作为OSX上的替代文件来在文件更改时运行任意命令。我觉得它简单而有用。



3

编辑: fsw已合并到中fswatch。在此答案中,fsw现在应阅读任何参考fswatch

fswatch用C ++ 编写了一个替代品,fsw它具有一些改进:

  • 这是一个GNU Build System项目,可在任何受支持的平台(OS X v。> = 10.6)上使用

    ./configure && make && sudo make install
    
  • 可以将多个路径作为不同的参数传递:

    fsw file-0 ... file-n 
    
  • 它转储带有所有事件信息的详细记录,例如:

    Sat Feb 15 00:53:45 2014 - /path/to/file:inodeMetaMod modified isFile 
    
  • 它的输出易于解析,因此fsw可以将其通过管道传输到另一个进程。

  • 可以使用来定制延迟-l, --latency
  • 可以用数字写事件标志,而不用文本写 -n, --numeric
  • 可以使用strftime带有格式字符串的时间格式来定制时间格式-t, --time-format
  • 时间可以是当地时间机器时间(默认情况下)或带有的UTC时间-u, --utc-time

获取fsw:

fsw托管在GitHub上,可以得到克隆其存储库:

    git clone https://github.com/emcrisostomo/fsw

安装fsw:

fsw 可以使用以下命令安装:

    ./configure && make && sudo make install

更多的信息:

我还写了一篇介绍性博客文章,您可以在其中找到几个有关fsw工作原理的示例。



2

我的fswatch分支提供的功能inotifywait -m具有更少的inotifywait解析性输出(没有等待,更多!在Linux上,我遇到了更多麻烦……)。

是对原始版本的改进 fswatch文件因为它通过STDOUT发送更改文件的实际路径,而不是要求您提供它分叉的程序。

作为一系列我用来自动执行某些操作的可怕bash脚本的基础,它一直坚如磐石。

inotifywait另一方面,在Linux上(这是不合时宜的),它上面需要很多麻烦,而且我仍然没有找到一种管理它的好方法,尽管我认为node.js可能是凭空买票的。


1
是的,fswatch的前叉。是那个在家酿?
fatuhoku 2013年

1
答案是不; 但是他们正在努力。要真正快速地安装它 brew install https://raw.github.com/mlevin2/homebrew/116b43eaef08d89054c2f43579113b37b4a2abd3/Library/Formula/fswatch.rb
fatuhoku

1

我有一个GIST,用法很简单

watchfiles <cmd> <paths...>

为了说明这一点,Hello World每次file1OR file2更改时,以下命令都会回显;默认的间隔检查是1秒

watchfiles 'echo Hello World' /path/to/file1 /path/to/file2 

如果我想每5秒检查一次,可以使用该-t标志

watchfiles -t 'echo Hello World' /path/to/file1 /path/to/file2 
  • -v 使 verbose显示调试信息模式
  • -q使watchfiles安静执行(#将显示,以便用户可以看到程序正在执行)
  • -qq 使 watchfiles完全安静地执行
  • -h 显示帮助和用法

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


0

我最终在macOS上这样做。我确信这在很多方面都是可怕的:

#!/bin/sh
# watchAndRun
if [ $# -ne 2 ]; then
    echo "Use like this:"
    echo "   $0 filename-to-watch command-to-run"
    exit 1
fi
if which fswatch >/dev/null; then
    echo "Watching $1 and will run $2"
    while true; do fswatch --one-event $1 >/dev/null && $2; done
else
    echo "You might need to run: brew install fswatch"
fi

没有一段时间,我无法弄清fswatch语法。这很烦人,使脚本难以停止。
丹·罗森斯塔克

0

如果要使用NodeJS,可以使用名为chokidar的包(实际上是chokidar-cli)进行观看,然后使用rsync(Mac随附):

Rsync命令:

$ rsync -avz --exclude 'some-file' --exclude 'some-dir' './' '/my/destination'

Chokidar cli(通过npm在全球安装):

chokidar \"**/*\" -c \"your-rsync-command-above\"


-3

对于没有watch命令但希望每3秒执行一次命令的用户,这是一种简单的单行替代方法:

while :; do your-command; sleep 3; done

这是一个无限循环,基本上与执行以下操作相同:

watch -n3 your-command


3
这与使用库监听文件系统中的事件不同。如果在您的示例your-command中进行磁盘I / O,则可以保证磁盘每3秒进行一次读/写- 每小时进行 10,800次通过使用文件系统事件,可以确保仅在更改文件时才会发生I / O(以及其他昂贵的操作)(通常只有一个小时几次)。
诺亚萨斯曼

是的,值得考虑。我通常需要watch暂时的时间查看事物在做什么。我没有将我提到的技术用于生产应用程序或类似的应用程序。例如,我希望看到的进度dd,并且我的技术可以实现(your-command适当替换以将适当的信号发送给dd)。
trusktr
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.