脚本如何检测文件变动

wen 实用脚本 29

本文目录导读:

脚本如何检测文件变动

  1. Python - watchdog 库(跨平台推荐)
  2. Linux - inotify(原生高效)
  3. Node.js - chokidar
  4. Bash - 简单轮询检测
  5. Windows - PowerShell
  6. Go - fsnotify
  7. macOS - fsevents(Swift)
  8. 性能对比
  9. 最佳实践建议

有多种方法可以检测文件变动,具体取决于你的使用场景和操作系统,以下是主流方案:

Python - watchdog 库(跨平台推荐)

from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class ChangeHandler(FileSystemEventHandler):
    def on_modified(self, event):
        if not event.is_directory:
            print(f"文件被修改: {event.src_path}")
    def on_created(self, event):
        print(f"文件被创建: {event.src_path}")
    def on_deleted(self, event):
        print(f"文件被删除: {event.src_path}")
# 监控当前目录
observer = Observer()
observer.schedule(ChangeHandler(), '.', recursive=True)
observer.start()
try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    observer.stop()
observer.join()

Linux - inotify(原生高效)

# 安装 inotify-tools
sudo apt-get install inotify-tools  # Debian/Ubuntu
# 监控文件变化
inotifywait -m -r -e modify,create,delete /path/to/watch

Shell 脚本示例:

#!/bin/bash
inotifywait -m -e modify,create,delete /path/to/watch | while read event
do
    echo "检测到变化: $event"
    # 执行你的操作
done

Node.js - chokidar

const chokidar = require('chokidar');
const watcher = chokidar.watch('/path/to/watch', {
    persistent: true,
    ignoreInitial: true
});
watcher
    .on('add', path => console.log(`文件 ${path} 被创建`))
    .on('change', path => console.log(`文件 ${path} 被修改`))
    .on('unlink', path => console.log(`文件 ${path} 被删除`));

Bash - 简单轮询检测

#!/bin/bash
file="/path/to/file.txt"
last_md5=$(md5sum "$file" | awk '{print $1}')
while true; do
    current_md5=$(md5sum "$file" | awk '{print $1}')
    if [ "$last_md5" != "$current_md5" ]; then
        echo "文件发生变化"
        last_md5=$current_md5
        # 执行操作
    fi
    sleep 1
done

Windows - PowerShell

# 使用 FileSystemWatcher
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\path\to\watch"
$watcher.Filter = "*.*"
$watcher.EnableRaisingEvents = $true
Register-ObjectEvent $watcher "Changed" -Action {
    Write-Host "文件 $($Event.SourceEventArgs.FullPath) 被修改"
}
# 保持脚本运行
while ($true) { Start-Sleep -Seconds 1 }

Go - fsnotify

package main
import (
    "log"
    "github.com/fsnotify/fsnotify"
)
func main() {
    watcher, _ := fsnotify.NewWatcher()
    defer watcher.Close()
    watcher.Add("/path/to/watch")
    for {
        select {
        case event := <-watcher.Events:
            log.Println("事件:", event)
        case err := <-watcher.Errors:
            log.Println("错误:", err)
        }
    }
}

macOS - fsevents(Swift)

import Foundation
let stream = FSEventStreamCreate(
    kCFAllocatorDefault,
    { _, _, _, eventPaths, _, _ in
        for path in eventPaths {
            print("文件变化: \(path)")
        }
    },
    nil,
    ["/path/to/watch"] as CFArray,
    FSEventStreamEventId(kFSEventStreamEventIdSinceNow),
    0.5,
    FSEventStreamCreateFlags(kFSEventStreamCreateFlagFileEvents)
)

性能对比

方法 平台 效率 延迟 准确性
inotify Linux 即时
fsevents macOS 即时
ReadDirectoryChangesW Windows 即时
watchdog 跨平台 即时
轮询(MD5) 所有 有延迟
时间戳检查 所有 有延迟

最佳实践建议

  1. 生产环境:使用操作系统原生API(inotify/fsevents/ReadDirectoryChanges)
  2. 跨平台需求:使用 watchdog (Python) 或 chokidar (Node.js)
  3. 简单脚本:使用 inotifywait (Linux) 或 md5sum 轮询
  4. 避免频繁读取:对大型文件使用变化通知而非轮询
  5. 处理批量事件:设置去抖(debounce)逻辑

选择哪种方案取决于你的操作系统、编程语言偏好和性能要求。

抱歉,评论功能暂时关闭!