watch_dir 1.0.1

Monitors a directory for file changes and delivers new UTF-8 content over a channel, with configurable read strategies.
Documentation

watch_dir

A Rust library that watches a directory for file changes and streams new content over a channel.

Most file-watching crates stop at detecting that a file changed. watch_dir goes further: it reads the file, applies a configurable strategy (tail new bytes, emit complete lines, re-read the whole file, or ignore), and delivers (path, content) pairs to your code via a std::sync::mpsc channel. Debouncing, offset tracking, and background threading are handled for you.

Usage

[dependencies]
watch_dir = "1.0.0"

Tail files in a directory

Emit each new complete line as it is appended to any file modified in the directory:

use watch_dir::{Watcher, Options, TAIL_LINES_STRATEGY};
use std::path::PathBuf;

fn main() {
    let watcher = Watcher::new(
        &PathBuf::from("/var/log/myapp"),
        Options::default(),
    ).unwrap();

    let rx = watcher.take_receiver().unwrap();

    for (path, line) in rx {
        println!("{}: {}", path.display(), line);
    }
}

Different strategy per file type

Use a selector function to choose how each file is read:

use watch_dir::{Watcher, Options, ReadStrategy};
use std::path::{Path, PathBuf};

fn strategy(path: &Path) -> ReadStrategy {
    match path.extension().and_then(|e| e.to_str()) {
        Some("log")  => ReadStrategy::TailLines, // emit complete lines as they appear
        Some("json") => ReadStrategy::Replace,   // re-read the whole file on each change
        Some("txt")  => ReadStrategy::Tail,      // emit appended text as it appears
        _            => ReadStrategy::Ignore,    // ignore anything that's not matched.
    }
}

fn main() {
    let watcher = Watcher::new(
        &PathBuf::from("/path/to/watch"),
        Options::new()
            .with_read_strategy_selector(strategy) // set your custom strategy,
            .with_recursive(true)                  // recursively watch subdirectories
    ).unwrap();

    let rx = watcher.take_receiver().unwrap();

    for (path, content) in rx {
        println!("{}: {}", path.display(), content);
    }
}

Read strategies

Strategy Behaviour
Tail Emit new text since the last read
TailLines Buffer new text; emit only complete newline-delimited lines
Replace Re-read the entire file on every change
Ignore Skip this file

Convenience constants TAIL_STRATEGY, TAIL_LINES_STRATEGY, and REPLACE_STRATEGY apply one strategy to all files. Pass a function fn(&Path) -> ReadStrategy to vary it per file.

Options

Method Default
with_read_strategy_selector(fn) TAIL_STRATEGY
with_recursive(bool) false
with_notify_debounce_duration(Duration) 250ms

Dependencies

  • notify — cross-platform file system event detection