A cross-platform Rust library for resolving XDG and platform-specific directories with proper fallbacks.
Most existing directory libraries (like dirs
) ignore XDG environment variables on macOS and Windows, defaulting to
platform-specific locations even when users have explicitly set XDG variables. This crate prioritizes XDG compliance
across all platforms while providing sensible platform-specific fallbacks.
- XDG-first approach: Respects XDG environment variables on all platforms
- Platform-aware fallbacks: Uses native conventions when XDG variables aren't set
- Cross-platform: Works on Linux, macOS, and Windows
- Zero dependencies: Only uses
std
library - Type-safe: Returns
Option<PathBuf>
for simple error handling
Add this to your Cargo.toml
:
[dependencies]
dir_spec = "0.5.0"
Basic usage:
fn main() {
// Get config directory (respects XDG_CONFIG_HOME if set)
if let Some(config_dir) = dir_spec::config_home() {
println!("Config: {}", config_dir.display());
}
// Get cache directory (respects XDG_CACHE_HOME if set)
if let Some(cache_dir) = dir_spec::cache_home() {
println!("Cache: {}", cache_dir.display());
}
// Get user's home directory
if let Some(home_dir) = dir_spec::home() {
println!("Home: {}", home_dir.display());
}
}
Method | XDG Variable | Linux Default | macOS Default | Windows Default |
---|---|---|---|---|
bin_home() |
XDG_BIN_HOME |
~/.local/bin |
~/.local/bin |
%LOCALAPPDATA%\Programs |
cache_home() |
XDG_CACHE_HOME |
~/.cache |
~/Library/Caches |
%LOCALAPPDATA% |
config_home() |
XDG_CONFIG_HOME |
~/.config |
~/Library/Application Support |
%APPDATA% |
config_local() |
— | ~/.config ¹ |
~/Library/Application Support ¹ |
%LOCALAPPDATA% |
data_home() |
XDG_DATA_HOME |
~/.local/share |
~/Library/Application Support |
%APPDATA% |
data_local() |
— | ~/.local/share ¹ |
~/Library/Application Support ¹ |
%LOCALAPPDATA% |
desktop() |
XDG_DESKTOP_DIR |
~/Desktop |
~/Desktop |
%USERPROFILE%\Desktop |
documents() |
XDG_DOCUMENTS_DIR |
~/Documents |
~/Documents |
%USERPROFILE%\Documents |
downloads() |
XDG_DOWNLOAD_DIR |
~/Downloads |
~/Downloads |
%USERPROFILE%\Downloads |
fonts() |
— | ~/.local/share/fonts |
~/Library/Fonts |
None ² |
home() |
HOME / USERPROFILE |
$HOME |
$HOME |
%USERPROFILE% |
music() |
XDG_MUSIC_DIR |
~/Music |
~/Music |
%USERPROFILE%\Music |
pictures() |
XDG_PICTURES_DIR |
~/Pictures |
~/Pictures |
%USERPROFILE%\Pictures |
preferences() |
— | ~/.config ¹ |
~/Library/Preferences |
%APPDATA% ¹ |
publicshare() |
XDG_PUBLICSHARE_DIR |
~/Public |
~/Public |
C:\Users\Public |
runtime() |
XDG_RUNTIME_DIR |
$TMPDIR or /tmp |
$TMPDIR or /tmp |
%TEMP% |
state_home() |
XDG_STATE_HOME |
~/.local/state |
~/Library/Application Support |
%LOCALAPPDATA% |
templates() |
XDG_TEMPLATES_DIR |
~/Templates |
~/Templates |
%USERPROFILE%\Templates |
videos() |
XDG_VIDEOS_DIR |
~/Videos |
~/Movies |
%USERPROFILE%\Videos |
Notes:
- Same as the corresponding
*_home()
function on non-Windows platforms - Returns
None
on Windows as there is no standard user fonts directory
config_home()
: Roaming config directory (synced across machines on Windows)config_local()
: Local config directory (machine-specific, not synced)
data_home()
: Roaming data directory (synced across machines on Windows)data_local()
: Local data directory (machine-specific, not synced)
config_home()
: General application configurationpreferences()
: Platform-specific preferences (macOS:.plist
files via Apple APIs)
fonts()
: User-installed fonts directory- Returns
None
on Windows as there's no standard user fonts directory
This crate always checks XDG environment variables first, regardless of platform:
// This will use XDG_CONFIG_HOME if set, even on macOS/Windows
export XDG_CONFIG_HOME="/custom/config/path"
let config = dir_spec::config_home(); // Returns Some("/custom/config/path")
If XDG variables aren't set, the crate falls back to platform-appropriate defaults.
Follows XDG Base Directory Specification defaults when XDG variables aren't set.
- Respects XDG variables if set (common among CLI tool users)
- Falls back to native macOS locations (
~/Library/Application Support
, etc.) - Uses
~/Movies
for videos (not~/Videos
) preferences()
points to~/Library/Preferences
for.plist
files
- Respects XDG variables if set
- Falls back to Windows conventions (
%APPDATA%
,%LOCALAPPDATA%
, etc.) - Public directory points to system-wide
C:\Users\Public
config_local()
anddata_local()
use%LOCALAPPDATA%
for non-roaming storagefonts()
returnsNone
(no standard user fonts directory)
All methods return Option<PathBuf>
. Methods return None
when:
- Home directory cannot be determined
- Required environment variables are missing (Windows-specific cases)
- Platform-specific directory resolution fails
- Directory doesn't exist on the platform (e.g.,
fonts()
on Windows)
match dir_spec::config_home() {
Some(path) => println!("Config dir: {}", path.display()),
None => eprintln!("Failed to get config dir"),
}
// Or using if-let
if let Some(config_path) = dir_spec::config_home() {
println!("Config dir: {}", config_path.display());
}
// For fallback handling
let config_dir = dir_spec::config_home().unwrap_or_else(|| {
// Fallback to current directory or panic, depending on your needs
std::env::current_dir().expect("Cannot determine current directory")
});
None! This crate only uses Rust's standard library.
Licensed under the MIT LICENSE
Contributions are welcome! Please ensure:
- All platforms are tested
- XDG compliance is maintained
- Platform-specific fallbacks follow native conventions
- New methods include appropriate documentation