[Rust] Pathに含まれる ~/ を展開する方法

2022/03/27に公開

はじめに

標準クレートの Path を一通り使ってみたところ、気の利いた作りになっているのがわかった。しかし、 Ruby の expand_path に相当する ~/ の展開を行なってくれないのが不便なので調べてみる。

標準で対応していた?

ホームディレクトリ自体は home_dir で取得できる。

std::env::home_dir()  // => Some("/Users/alice")

にもかかわらず展開してくれないのは home_dir が非推奨だからのようだ。上のコードをコンパイルすると下の警告が出る。

warning: use of deprecated function `std::env::home_dir`: This function's behavior is unexpected and probably not what you want. Consider using a crate from crates.io instead.

外部クレートを探す

そこで外部クレートと探すろ home-dir というそれっぽいのを見つけたので使ってみる。

use std::path::Path;
use home_dir::*;

Path::new("~/src").expand_home()  // => Ok("/Users/alice/src")

これだー!!

どういう実装?

覗いてみるとこうなっていた。

まず環境変数 HOME を見る。

use std::env;
env::var("HOME")  // => Ok("/Users/alice")

取れなければ uid から何かをあれして取得する。

use nix::unistd::{Uid, User};
let uid = Uid::current();
User::from_uid(uid).unwrap().unwrap().dir  // => "/Users/alice"

外部クレートの nix はUNIXに依存した情報を取得できるらしい。

はまったこと

home_dirnix に依存しているからといって home_dir を使うプログラムから use nix とはできない。つまり孫関係の依存ライブラリは使うことができない。良し悪しありそうだが Rust はスコープを明確にする方針のようだ。

Discussion