【问题标题】:How do you write a Scala script that will react to file changes您如何编写对文件更改做出反应的 Scala 脚本
【发布时间】:2021-03-25 22:48:23
【问题描述】:

我想将以下批处理脚本更改为 Scala(只是为了好玩),但是,该脚本必须继续运行并监听 *.mkd 文件的更改。如果任何文件发生更改,则脚本应重新生成受影响的文档。文件 IO 一直是我的致命弱点……

#!/bin/sh
for file in *.mkd
do
  pandoc --number-sections $file -o "${file%%.*}.pdf"
done

任何关于解决此问题的好方法的想法都将受到赞赏。

【问题讨论】:

  • 使用 Java WatchService
  • 谢谢鲍里斯。这似乎是最好的方法。

标签: scala


【解决方案1】:

以下代码,取自我的回答:Watch for project files also 可以监视目录并执行特定命令:

#!/usr/bin/env scala

import java.nio.file._
import scala.collection.JavaConversions._
import scala.sys.process._

val file = Paths.get(args(0))
val cmd = args(1)
val watcher = FileSystems.getDefault.newWatchService

file.register(
  watcher, 
  StandardWatchEventKinds.ENTRY_CREATE,
  StandardWatchEventKinds.ENTRY_MODIFY,
  StandardWatchEventKinds.ENTRY_DELETE
)

def exec = cmd run true

@scala.annotation.tailrec
def watch(proc: Process): Unit = {
  val key = watcher.take
  val events = key.pollEvents

  val newProc = 
    if (!events.isEmpty) {
      proc.destroy()
      exec
    } else proc

  if (key.reset) watch(newProc)
  else println("aborted")
}

watch(exec)

用法:

watchr.scala markdownFolder/ "echo \"Something changed!\""

必须对脚本进行扩展才能将文件名注入命令。到目前为止,这个 sn-p 应该被视为实际答案的构建块。

修改脚本以包含 *.mkd 通配符并非易事,因为您必须手动搜索文件并在所有文件上注册监视。重复使用上面的脚本并将所有文件放在一个目录中,还有一个额外的好处是可以在创建新文件时获取它们。

正如您所看到的,仅依靠 Scala 和 Java API 很快就会变得非常庞大和混乱,您最好还是依靠替代库或在使用 INotify 时坚持使用 bash。

【讨论】:

  • 谢谢鲍勃,它几乎可以工作了。但是,参数会在某处丢失。如果您执行了whatchr.scala folder/ "echo $file",那么它只会回显空行,而不仅仅是文件更改。感谢您到目前为止的帮助;-)
  • 哎呀,你说得对,我很愚蠢,我将修改答案,解释需要进行的其他更改。目前的代码应该只是作为 Scala 中 WatchService 的示例。
  • 还有schwatcher 项目将WatchService API 封装在更人性化的抽象中。
猜你喜欢
  • 2015-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-01
  • 2016-08-09
  • 1970-01-01
  • 1970-01-01
  • 2015-04-26
相关资源
最近更新 更多