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

I am Jan Bodnar, a programmer and technical writer. I have been writing programming tutorials at ZetCode since 2007 and have published eight e-books. See about the author.

List all Dart tutorials.