How do I get the directory of the current script, in Dart?
If you're doing this for a console based app (e.g. in a unit test) and intend to use the output to open a file for reading or writing, it's more helpful to use Platform.script.path
:
import "package:path/path.dart" show dirname, join;
import 'dart:io' show Platform;
main() {
print(join(dirname(Platform.script.path), 'test_data_file.dat'));
}
The result of that command can be used with a File
object and be opened/read (e.g. if you have a unit test that needs to read/compare sample data, or a console program that needs to open a file relative to the current script for some other reason).
The easiest way to find the script's directory is to use the path package.
import "package:path/path.dart" show dirname;
import 'dart:io' show Platform;
main() {
print(dirname(Platform.script.toString()));
}
Put the path package into your pubspec.yaml:
dependencies:
path: any
And be sure to run pub get
to download and link the path package.
Using Platform.script.path doesn't work in all circumstances.
If your script is compiled or running as a unit test you won't get the expected results.
This is from the dcli project (https://pub.dev/packages/dcli)
If you are using dcli you can call:
// absolute path including the script name
DartScript.self.pathToScript;
or
// just the absolute path to the script's directory
DartScript.self.pathToScriptDirectory;
This code works if the script is run via dart <scriptname.dart>, if you compile the script or if you script is a unit test.
Here is the internal implementation.
static String get _pathToCurrentScript {
if (_current == null) {
final script = Platform.script;
String _pathToScript;
if (script.isScheme('file')) {
_pathToScript = Platform.script.toFilePath();
if (_isCompiled) {
_pathToScript = Platform.resolvedExecutable;
}
} else {
/// when running in a unit test we can end up with a 'data' scheme
if (script.isScheme('data')) {
final start = script.path.indexOf('file:');
final end = script.path.lastIndexOf('.dart');
final fileUri = script.path.substring(start, end + 5);
/// now parse the remaining uri to a path.
_pathToScript = Uri.parse(fileUri).toFilePath();
}
}
return _pathToScript;
} else {
return _current.pathToScript;
}
}
static bool get _isCompiled =>
basename(Platform.resolvedExecutable) ==
basename(Platform.script.path);
Another (albeit hacky) way to determine the path to the current .dart
file is to extract the path from the stack trace.
Unlike Platform.script.path
, this should work with unit tests:
import 'package:stack_trace/stack_trace.dart' as stacktrace;
String currentDartFilePath() => stacktrace.Frame.caller(1).library;
Note that this will return a path relative to (I think) the caller's package root. Also note that stacktrace.Frame.caller(1).library
returns the path to the caller, so the above expects that you call currentDartFilePath()
and not stacktrace.Frame.caller(1).library
directly.
If you want just the directory, you then can perform typical path manipulation operations on the result.