327

我想在我的 Mac(Snow Leopard)上观看一个文件夹,然后执行一个脚本(给它刚刚移动到文件夹中的文件名(作为参数...... x.sh“文件名”))。

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

有这样的命令吗?

4

16 回答 16

498

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

注意:-o如果xargs不是-I{}. 如果您确实选择使用该数字,请将其{}放在命令中的任何位置。

版本 0.x的旧方式:

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

使用 Homebrew 安装

截至 2013 年 9 月 12 日,它被重新添加到自制软件中- 耶!因此,更新您的公式列表 ( 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 命令行工具 - 两者都是免费的。但是,如果是这种情况,您可能应该只检查 homebrew

fswatch1.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.
于 2012-12-10T19:37:14.783 回答
103

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

例如,/usr/bin/logger当我的用户帐户的桌面文件夹被修改时,以下 launchd config 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 文件夹中。

然后,您可以在 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手册页。

于 2009-10-04T09:40:29.970 回答
43

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

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

$ watchman watch ~/src

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

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

于 2014-04-07T08:33:19.073 回答
23

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

于 2012-01-24T22:49:07.860 回答
16

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

于 2012-05-11T13:00:22.087 回答
12

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

  • brew install entr在 macOS 上
  • apt install entr在 Debian/Ubuntu 上
于 2016-10-18T09:13:30.000 回答
6

sschober这是一个使用's tool的单行代码。

$ while true; do kqwait ./file-to-watch.js; script-to-execute.sh; done
于 2016-04-24T18:51:54.707 回答
3

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

于 2009-10-04T06:16:29.893 回答
3

编辑: fsw已合并到fswatch. 在这个答案中,任何对的引用fsw现在都应该是fswatch.

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

  • 这是一个 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.
  • 可以使用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工作原理的示例。

于 2014-02-15T00:30:59.320 回答
2

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

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

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

(这是题外话)inotifywait另一方面,在 Linux 上需要很多杂乱无章的东西,我仍然没有找到管理它的好方法,尽管我认为基于某些东西node.js可能是门票。

于 2013-05-22T03:24:48.600 回答
1

我有一个 GIST,用法很简单

watchfiles <cmd> <paths...>

为了说明,以下命令将在Hello World每次file1ORfile2更改时回显;并且默认间隔检查是 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

于 2017-04-05T07:45:25.330 回答
1

我最终为 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
于 2019-02-02T17:48:12.803 回答
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\"

于 2019-10-08T00:00:33.067 回答
0

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

于 2021-09-16T14:28:42.947 回答
-1

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

于 2022-03-02T11:13:29.487 回答
-3

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

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

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

watch -n3 your-command

于 2013-11-11T08:39:08.497 回答