Dart FileSystemMoveEvent
last modified October 18, 2026
The FileSystemMoveEvent class in Dart represents file system move
or rename operations. It's part of Dart's file system event monitoring API.
This event is triggered when files or directories are moved or renamed within a watched directory. It provides details about both old and new paths.
Basic Definition
FileSystemMoveEvent is a subclass of FileSystemEvent.
It contains information about file/directory move operations in the file system.
Key properties include the old path (source) and the new path (destination) of
the moved item. The destination is nullable because some platforms cannot always
determine it. The event is emitted by Directory.watch() when moves
occur.
Basic FileSystemMoveEvent Usage
This example shows how to watch for file move events in a directory.
import 'dart:io';
void main() async {
var dir = Directory('test_dir');
await dir.create();
var subscription = dir.watch().listen((event) {
if (event is FileSystemMoveEvent) {
print('Move detected:');
print(' From: ${event.path}');
print(' To: ${event.destination ?? '(unknown)'}');
print(' Type: ${event.runtimeType}');
}
});
// Simulate a file move
var file = File('${dir.path}/test.txt');
await file.create();
await file.rename('${dir.path}/renamed.txt');
await Future.delayed(Duration(seconds: 1));
await subscription.cancel();
}
We create a directory watcher and listen for move events. When a file is renamed,
the event provides the original path and a nullable destination. The concrete
event type is FileSystemMoveEvent.
$ dart main.dart Move detected: From: test_dir/test.txt To: test_dir/renamed.txt Type: FileSystemMoveEvent
Handling Directory Moves
This example demonstrates detecting directory move operations.
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('Directory moved:');
print(' Source: ${event.path}');
print(' Target: ${event.destination ?? '(unknown)'}');
}
});
// Create and move a subdirectory
var subDir = Directory('${dir.path}/subdir');
await subDir.create();
await subDir.rename('${dir.path}/moved_subdir');
await Future.delayed(Duration(seconds: 1));
await subscription.cancel();
}
Directory moves trigger similar events to file moves. The event contains the original and new paths of the moved directory.
$ dart main.dart Directory moved: Source: watch_dir/subdir Target: watch_dir/moved_subdir
Renames and Moves Out of a Directory
This example shows how renames and moves are reported by a non-recursive directory watcher.
import 'dart:io';
void main() async {
var dir = Directory('monitor_dir');
await dir.create();
var subscription = dir.watch().listen((event) {
if (event is FileSystemMoveEvent) {
var destination = event.destination;
print('Renamed/moved within watched directory:');
print(' Old: ${event.path}');
print(' New: ${destination ?? '(unknown)'}');
} else if (event is FileSystemDeleteEvent) {
print('Removed or moved out of watched directory: ${event.path}');
}
});
// Rename within the watched directory
var file = File('${dir.path}/original.txt');
await file.create();
await file.rename('${dir.path}/renamed.txt');
// Move into a subdirectory. On Linux this is reported as a delete of the
// source path because the non-recursive watcher does not see the subdirectory.
var newDir = Directory('${dir.path}/new_location');
await newDir.create();
await File('${dir.path}/renamed.txt')
.rename('${newDir.path}/moved.txt');
await Future.delayed(Duration(seconds: 1));
await subscription.cancel();
}
A rename whose destination stays in the watched directory produces a
FileSystemMoveEvent with both paths. Moving a file into a
subdirectory is reported differently: on Linux the non-recursive watcher sees
the source path disappear and emits a FileSystemDeleteEvent.
Recursive watching would capture the destination, but Dart's Linux backend does
not support recursive watches.
$ dart main.dart Renamed/moved within watched directory: Old: monitor_dir/original.txt New: monitor_dir/renamed.txt Removed or moved out of watched directory: monitor_dir/renamed.txt
Error Handling in Move Events
This example demonstrates error handling during file system move operations.
import 'dart:io';
void main() async {
var dir = Directory('error_dir');
await dir.create();
var subscription = dir.watch().listen((event) {
if (event is FileSystemMoveEvent) {
print('Move event detected');
var destination = event.destination;
if (destination == null) {
print('Destination unknown');
return;
}
print('Destination exists: ${File(destination).existsSync()}');
}
});
var file = File('${dir.path}/testfile.txt');
await file.create();
await file.rename('${dir.path}/renamed.txt');
// Move to invalid location: no move event is emitted for a failed rename
try {
await File('${dir.path}/renamed.txt')
.rename('${dir.path}/nonexistent/subdir/file.txt');
} on FileSystemException catch (e) {
print('Move failed: ${e.message}');
}
await Future.delayed(Duration(seconds: 1));
await subscription.cancel();
}
A move event is emitted only after a successful rename, so the destination can
be validated safely. A failed rename throws a FileSystemException
instead of producing an event.
$ dart main.dart Move event detected Destination exists: true Move failed: Cannot rename file to 'error_dir/nonexistent/subdir/file.txt'
Monitoring Multiple Events
This example shows handling multiple event types including move events.
import 'dart:io';
void main() async {
var dir = Directory('multi_event_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.move:
var destination = (event as FileSystemMoveEvent).destination;
print('Move event: ${event.path} → ${destination ?? '(unknown)'}');
break;
case FileSystemEvent.create:
print('Create event: ${event.path}');
break;
case FileSystemEvent.delete:
print('Delete event: ${event.path}');
break;
case FileSystemEvent.modify:
print('Modify event: ${event.path}');
break;
}
});
// Trigger various events
var file = File('${dir.path}/demo.txt');
await file.create();
await file.writeAsString('content');
var renamed = await file.rename('${dir.path}/renamed_demo.txt');
await renamed.delete();
await Future.delayed(Duration(seconds: 1));
await subscription.cancel();
}
We handle all file system event types with a switch statement. Move events are specifically cast to access the nullable destination property. Each event type has its own case.
$ dart main.dart Create event: multi_event_dir/demo.txt Modify event: multi_event_dir/demo.txt Move event: multi_event_dir/demo.txt → multi_event_dir/renamed_demo.txt Delete event: multi_event_dir/renamed_demo.txt
Best Practices
- Filter events: Check event types before processing
- Handle errors: Validate paths after move events
- Resource management: Close watchers when done
- Performance: Avoid heavy processing in event handlers
- Cross-platform: Test behavior on different OSes
Source
Dart FileSystemMoveEvent Documentation
This tutorial covered Dart's FileSystemMoveEvent class with practical examples showing file and directory move detection, error handling, and event processing.
Author
List all Dart tutorials.