Reputation: 120749
I want to know what the script's directory is. I have a command-line Dart script.
Upvotes: 19
Views: 9097
Reputation: 90155
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;
/// Returns an absolute path to the caller's `.dart` file.
String currentDartFilePath() => stacktrace.Frame.caller(1).uri.toFilePath();
/// Returns a path to the caller's `.dart` file, relative to the package root.
String currentPackageRelativePath() => stacktrace.Frame.caller(1).library;
Note that stacktrace.Frame.caller(1)
returns the stack frame of the caller, so the code above expects that you call currentDartFilePath()
currentPackageRelativePath()
and not use stacktrace.Frame.caller(1).uri.toFilePath()
or stacktrace.Frame.caller(1).library
directly.
If you want just the directory, you then can perform typical path manipulation operations on the results.
Upvotes: 2
Reputation: 4584
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);
Upvotes: 5
Reputation: 21661
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).
Upvotes: 18
Reputation: 120749
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.
Upvotes: 9