ZetCode

Dart Link

last modified October 18, 2026

The Link class in Dart provides a way to work with symbolic links on the file system. It is part of the dart:io library for server-side and command-line applications.

A Link represents a symbolic link: a directory entry that points to another path. It allows creating, inspecting, updating, and deleting links programmatically.

Basic Definition

Link is a concrete FileSystemEntity that represents a symbolic link. It inherits the common entity operations such as exists(), delete(), stat(), and watch().

Key features include creating a link to a target path, reading the target with target(), replacing the target with update(), and removing the link without affecting its target. The Link class does not read or write file contents; use a File for that.

Creating a Symbolic Link

This example shows how to create a symbolic link to an existing file.

main.dart
import 'dart:io';

void main() async {
  var target = File('target.txt');
  await target.writeAsString('Hello from the target file\n');
  
  var link = Link('link.txt');
  await link.create(target.path);
  
  print('Created link: ${link.path}');
  print('Link target: ${await link.target()}');
  print(await File(link.path).readAsString());
  
  await link.delete();
  await target.delete();
}

We write a target file and create a Link that points to it. The target() method returns the path stored in the link, and reading the link path through a File follows the link to the target.

$ dart main.dart
Created link: link.txt
Link target: target.txt
Hello from the target file

Reading a Link Target

This example demonstrates checking a link and reading the path it points to.

main.dart
import 'dart:io';

void main() async {
  var target = File('target.txt');
  await target.writeAsString('data');
  
  var link = Link('link.txt');
  await link.create(target.path);
  
  print('Link exists: ${await link.exists()}');
  print('Points to: ${await link.target()}');
  
  await link.delete();
  await target.delete();
}

Link.exists() checks for the link itself, while target() returns the target path exactly as it was stored when the link was created.

$ dart main.dart
Link exists: true
Points to: target.txt

Updating a Link

This example shows how to point an existing link at a different target.

main.dart
import 'dart:io';

void main() async {
  var first = File('first.txt');
  var second = File('second.txt');
  await first.writeAsString('first');
  await second.writeAsString('second');
  
  var link = Link('current.txt');
  await link.create(first.path);
  print('Initially: ${await link.target()}');
  
  await link.update(second.path);
  print('After update: ${await link.target()}');
  print(await File(link.path).readAsString());
  
  await link.delete();
  await first.delete();
  await second.delete();
}

update() deletes the existing link and recreates it with the new target path. The target files themselves are not modified.

$ dart main.dart
Initially: first.txt
After update: second.txt
second

Checking Link Type

This example demonstrates distinguishing a symbolic link from its target.

main.dart
import 'dart:io';

void main() async {
  var target = File('target.txt');
  await target.writeAsString('target content');
  
  var link = Link('link.txt');
  await link.create(target.path);
  
  var linkType = await FileSystemEntity.type(link.path, followLinks: false);
  var targetType = await FileSystemEntity.type(link.path);
  
  print('Link type: $linkType');
  print('Target type: $targetType');
  
  await link.delete();
  await target.delete();
}

By default FileSystemEntity.type() follows links and reports the target's type. Passing followLinks: false reports FileSystemEntityType.link for the link itself.

$ dart main.dart
Link type: link
Target type: file

Creating Multiple Links

This example shows how to create several links in a loop.

main.dart
import 'dart:io';

void main() async {
  var targets = {
    'readme.txt': 'Read me first',
    'config.json': '{"debug": false}',
  };
  
  for (var entry in targets.entries) {
    await File(entry.key).writeAsString(entry.value);
  }
  
  var links = <String, Link>{};
  for (var name in targets.keys) {
    var link = Link('link_$name');
    await link.create(name);
    links[name] = link;
  }
  
  for (var entry in links.entries) {
    print('${entry.value.path} -> ${await entry.value.target()}');
  }
  
  for (var link in links.values) {
    await link.delete();
  }
  for (var name in targets.keys) {
    await File(name).delete();
  }
}

Each link maps a separate name to an existing target file. After printing the mappings, the links are removed first and then the target files are deleted.

$ dart main.dart
link_readme.txt -> readme.txt
link_config.json -> config.json

Deleting a Link

This example shows that deleting a link leaves its target untouched.

main.dart
import 'dart:io';

void main() async {
  var target = File('target.txt');
  await target.writeAsString('keep me');
  
  var link = Link('link.txt');
  await link.create(target.path);
  
  await link.delete();
  print('Link exists: ${await link.exists()}');
  print('Target exists: ${await target.exists()}');
  
  await target.delete();
}

Deleting a Link removes only the directory entry, not the target file. The target remains available at its original path.

$ dart main.dart
Link exists: false
Target exists: true

Best Practices

Source

Dart Link Documentation

This tutorial covered Dart's Link class with practical examples showing symbolic link creation, target inspection, updates, type checks, and deletion.

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.