ZetCode

Dart FileSystemEvent

last modified October 18, 2026

The FileSystemEvent class in Dart represents changes in the file system. It's used with Directory.watch() to monitor files and directories.

FileSystemEvent provides information about create, modify, delete, and move operations. It's part of Dart's dart:io library for I/O operations.

Basic Definition

FileSystemEvent is a sealed base class with concrete subclasses for different event types. These include create, modify, delete, and move events.

Key properties include path, type, and (for move events) destination path. Events are delivered asynchronously through streams from Directory.watch().

Basic File Monitoring

This example shows basic file system monitoring using FileSystemEvent.

main.dart
import 'dart:io';

void main() async {
  var dir = Directory('watch_dir');
  await dir.create();
  
  var subscription = dir.watch().listen((event) {
    print('Event type: ${event.runtimeType}');
    print('Path: ${event.path}');
    
    if (event is FileSystemMoveEvent) {
      print('Destination: ${event.destination ?? '(unknown)'}');
    }
  });
  
  await File('${dir.path}/newfile.txt').create();
  await Future.delayed(Duration(seconds: 1));
  await subscription.cancel();
}

We create a watcher for a directory, trigger one create event, and then cancel the subscription. The code prints the concrete event class and path, including special handling for move events.

$ dart main.dart
Event type: FileSystemCreateEvent
Path: watch_dir/newfile.txt

Filtering Specific Event Types

This example demonstrates filtering for specific file system event types.

main.dart
import 'dart:io';

void main() async {
  var dir = Directory('watch_dir');
  await dir.create();
  
  var seen = <String>{};
  var subscription = dir.watch().listen((event) {
    if (!seen.add('${event.type}:${event.path}')) return;
    
    switch (event.type) {
      case FileSystemEvent.create:
        print('File created: ${event.path}');
        break;
      case FileSystemEvent.modify:
        print('File modified: ${event.path}');
        break;
      case FileSystemEvent.delete:
        print('File deleted: ${event.path}');
        break;
    }
  });
  
  var file = File('${dir.path}/test.txt');
  await file.create();
  await file.writeAsString('content');
  await file.delete();
  await Future.delayed(Duration(seconds: 1));
  await subscription.cancel();
}

We watch a specific directory and handle different event types separately. This allows customized responses to different file system operations.

$ dart main.dart
File created: watch_dir/test.txt
File modified: watch_dir/test.txt

Handling Move Events

This example focuses on detecting and handling file move/rename operations.

main.dart
import 'dart:io';

void main() async {
  var dir = Directory('watch_dir');
  await dir.create();
  
  var subscription = dir.watch().listen((event) {
    if (event is FileSystemMoveEvent) {
      print('File moved/renamed:');
      print('From: ${event.path}');
      print('To: ${event.destination ?? '(unknown)'}');
      print('Is directory: ${event.isDirectory}');
    }
  });
  
  var file = await File('${dir.path}/old.txt').create();
  await file.rename('${dir.path}/new.txt');
  await Future.delayed(Duration(seconds: 1));
  await subscription.cancel();
}

Move events are special as they include both source and destination paths. The destination is nullable because some platforms cannot always determine it, and the isDirectory property indicates if the moved item is a file or directory.

$ dart main.dart
File moved/renamed:
From: watch_dir/old.txt
To: watch_dir/new.txt
Is directory: false

Watching Recursively

This example shows how to monitor a directory and all its subdirectories.

main.dart
import 'dart:io';

void main() async {
  var dir = Directory('watch_dir');
  await dir.create(recursive: true);
  
  var subscription = dir.watch(recursive: true).listen((event) {
    print('Event in ${event.isDirectory ? 'directory' : 'file'}:');
    print('Path: ${event.path}');
    print('Type: ${event.runtimeType}');
  });
  
  await Directory('${dir.path}/subdir').create();
  await Future.delayed(Duration(seconds: 1));
  await subscription.cancel();
}

The recursive flag asks the platform to extend monitoring to subdirectories. This works on Windows and macOS; on Linux Dart uses inotify without recursive watches, so only entries in the top directory are reported. We also check whether each event affects a file or directory.

$ dart main.dart
Event in directory:
Path: watch_dir/subdir
Type: FileSystemCreateEvent

Error Handling in File Watching

This example demonstrates proper error handling for file system watching.

main.dart
import 'dart:io';

void main() async {
  var dir = Directory('nonexistent_dir');
  await dir.create();
  
  var subscription = dir.watch().listen(
    (event) {
      print('Event: ${event.runtimeType} at ${event.path}');
    },
    onError: (Object error) {
      print('Error watching directory: $error');
    },
  );
  
  await dir.delete();
  await Future.delayed(Duration(seconds: 1));
  await subscription.cancel();
}

The listener's onError callback receives asynchronous watcher errors, such as an inaccessible path. We also cancel the subscription after the watched directory is deleted.

$ dart main.dart
Event: FileSystemDeleteEvent at nonexistent_dir

Best Practices

Source

Dart FileSystemEvent Documentation

This tutorial covered Dart's FileSystemEvent class with practical examples showing file system monitoring, event handling, and error management.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Dart tutorials.