ChatGPT解决这个技术问题 Extra ChatGPT

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

我想在我的 Mac 上查看一个文件夹,然后执行一个 bash 脚本,将刚刚移动到或在监视目录中创建的任何文件/文件夹的名称传递给它。

您应该询问 DropBox 是如何做到的,因为大概他们尝试了所有可用的选项。
@JeffBurdges 我不太确定这会是一件容易的事。但是,我会在浏览 Apple 的 FSEvents Reference 后说,如果 Dropbox 不使用它,那将是非常愚蠢的。下面作为答案提供的 fswatch 实用程序实际上确实使用了这种方法。
@JeffBurdges:这不好笑。

M
Mateen Ulhaq

fswatch

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

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

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

语法 / 一个简单的例子

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

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

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

0.x 版本的旧方式:

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

使用 Homebrew 安装

自 2013 年 9 月 12 日起,它已重新添加到 homebrew - 是的!因此,更新您的公式列表 (brew update),然后您需要做的就是:

brew install fswatch

没有 Homebrew 的安装

Terminal.app 中键入这些命令

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

如果您的系统上没有 c 编译器,您可能需要安装 Xcode 或 Xcode 命令行工具 - 两者都是免费的。但是,如果是这种情况,您可能应该只使用 check out 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 的错误。幸运的是,fswatch 现在在 MacPorts 上,所以 sudo port install fswatch 对于我们这些使用 MacPorts 而不是 Homebrew 的人有效。
如果您正在使用带有静态参数的命令(例如,我在 src 上运行单元测试并测试更改),这可能不适合您。这个问题 (stackoverflow.com/questions/25689589/…) 是我需要的第二个问题。
我听到你的声音:fswatch ./ | xargs -I{} cp {} ~/Dropbox/backup/latest/
fswatch 比 entr 或 when_changed 之类的工具要好,后者在处理 .git 目录时会出现一些错误。 fswatch 更专业。简单地说,您只需 fswatch . 将监视当前目录。
对于 NULL,我建议使用 fswatch -0 -v -o /path/to/watched/files | xargs -0 -n 1 -I {} [your command]-0。这个对我有用,可以减少编译
s
sakra

您可以为此目的使用 launchd。 Launchd 可以配置为在修改文件路径时自动启动程序。

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

<?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 文件夹中。

然后,您可以在 shell 中使用命令 launchctl 通过运行以下命令来激活 logger.plist:

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

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

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

上面的配置文件使用 WatchPaths 选项。或者,您也可以使用 QueueDirectories 选项。有关详细信息,请参阅 launchd 手册页。


有没有办法让它监视文件内容和文件路径的变化?
我不这么认为。您可以为此目的使用 opensnoop
我让它工作了,但是当我用我的 Bash 脚本切换 /usr/bin/logger 并删除 "<string>path modified</strong>" 条目时,我找不到任何方法让我的 bash 脚本知道我桌面上的哪个文件被修改了 - 就是这样事件发生。我尝试查看 $0$1 并且只获得了脚本名称本身,并注意到传递给它。
此外,一旦检测到更改,这个东西是否会进入循环,而不是仅在检测到更改时启动(和停止)?我宁愿它按需工作,而不是一直循环运行告诉我,例如,2 天前,我的桌面上发生了一些变化,一遍又一遍地写在日志中。那么,我们是否需要在这个 plist 中使用某种间隔选项?
伟大的工作和解释
J
Jakub Holý

Facebook 的 watchman 可通过 Homebrew 获得,看起来也不错。它还支持过滤:

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

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


这是迄今为止最好的工具。
这是一个非常好的小程序:文档很棒,它不会打开无限循环(fswatch 似乎就是这样做的),它会记住您在重新启动后创建的手表并再次自动启动它们。
@BentOnCoding 你能详细说明你是如何得出这个结论的吗?
我进行了大量研究,比较了各种解决方案。该功能非常强大,并且始终如一地工作。
s
sschober

您可能想看看(并可能扩展)我的小工具 kqwait。目前它只是坐在那里等待单个文件上的写入事件,但 kqueue 架构允许分层事件堆叠......


到目前为止在山狮上工作。非常好!
所以这真的很棒。我在使用 fswatch 时遇到了一个小问题(这也很好,因为它是一个轻量级的包装器,我确信它也可以被修改以做正确的事情)在运行 git status 之类的东西时它会触发(其中实际上每次在我的机器上呈现 zsh 提示时都会运行...)这实际上通过创建一个无休止的反馈循环来搞砸我拥有的这个精心制作的脚本。但是,kqwait 提供有关已更改文件的信息,并且不会被 git status 触发。我确实需要它在写入时触发。
$ brew install kqwait && while true; do kqwait doc/my_file.md; make; done
很简单,在 Mojave 上就像一个魅力(可能在任何未来的 Mac OS 上)。
g
gfxmonk

watchdog 是一个用于监视文件/目录的跨平台 python API,它具有内置的“技巧”工具,允许您在事件发生时触发操作(包括 shell 命令)(包括新添加的文件、删除的文件和更改的文件) .


u
unhammer

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

在 macOS 上 brew install entr

在 Debian/Ubuntu 上 apt install entr


O
Oleg Dater

这是使用 sschobertool 的单行代码。

$ while true; do kqwait ./file-to-watch.js; script-to-execute.sh; done

$ brew install kqwait
A
Asaph

Apple OSX Folder Actions 允许您根据对文件夹执行的操作自动执行任务。


是的,我知道,我尝试过多次使用它,但从未成功使用它,你能给我举个例子吗?
这是链接,不是答案
E
Enrico M. Crisostomo

编辑: fsw 已合并到 fswatch。在此答案中,对 fsw 的任何引用现在都应为 fswatch

我用 C++ 编写了一个名为 fswfswatch 替代品,它具有多项改进:

这是一个 GNU 构建系统项目,它构建在任何受支持的平台 (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 写入数字事件标志而不是文本标志。

可以使用带有 -t、--time-format 的 strftime 格式字符串自定义时间格式。

时间可以是机器的本地时间(默认情况下)或带有 -u、--utc-time 的 UTC 时间。

获取 fsw:

fswhosted on GitHub,可以通过克隆其存储库获得:

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

安装 fsw:

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

    ./configure && make && sudo make install

更多信息:

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


S
Steven Lu

我的 fswatch 分支提供了 inotifywait -m 的功能,但对解析友好的输出略少(不用等待,更多!我在使用 inotifywait 的 Linux 上遇到的麻烦更多...)。

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

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

(这是题外话)另一方面,Linux 上的 inotifywait 需要大量的杂项,我仍然没有找到管理它的好方法,尽管我认为基于 {2 } 可能是票。


对,fswatch 的分支。是在 Homebrew 上吗?
答案是不;但他们是working on it。要真正快速地安装它,只需 brew install https://raw.github.com/mlevin2/homebrew/116b43eaef08d89054c2f43579113b37b4a2abd3/Library/Formula/fswatch.rb
t
thiagoh

我有一个 GIST,用法很简单

watchfiles <cmd> <paths...>

为了说明,以下命令将在每次 file1 OR file2 更改时回显 Hello World;并且默认间隔检查是 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 启用显示调试信息的详细模式

-q 让监视文件安静地执行(将显示#,以便用户可以看到程序正在执行)

-qq 使监视文件完全安静地执行

-h 显示帮助和用法

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


D
Dan Rosenstark

我最终为 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 语法。这很烦人,使脚本难以停止。
p
prograhammer

如果您想使用 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\"


u
user16929228

sudo fs_usage -f 文件系统 | grep“有趣的事情”?


这是一个问题还是一个答案?
欢迎来到堆栈溢出!虽然此代码可能会解决问题,但including an explanation如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提出问题的人。请edit您的回答以添加解释并说明适用的限制和假设。
感谢您发布直接在终端上运行而无需安装第三方软件的唯一选项。
j
jmagnusson

我可以全心全意地推荐使用 watchexec。内置 Rust 和 It Just Works™,无论您在哪个平台上!简单的 CLI 选项也是如此。


t
trusktr

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

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

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

watch -n3 your-command


这与使用侦听来自文件系统的事件的库不同。如果在您的示例中,your-command 执行磁盘 I/O,那么这是 保证 磁盘读取/写入每 3 秒 - 或每 小时 10,800 次。 通过使用文件系统事件您可以保证 I/O(和其他昂贵的操作)仅在您更改文件时发生(通常每小时只有几次。)
是的,值得考虑。我通常需要 watch 暂时的时间来看看某事在做什么。我不会将我提到的技术用于生产应用程序或类似的东西。例如,我想查看 dd 的进度,并且我的技术实现了它(根据需要替换 your-command 以向 dd 发送适当的信号)。