rust の std::path::Path のつまづきポイント
rust の std::path::Path はパスを扱うための標準ライブラリです。 std::path::Path を使う上でつまづきそうなポイントをまとめました。
動作確認は rustc 1.43.0 (4fb7144ed 2020-04-20)
で行いました。
/
or \
Unix では /
のみ、 Windows では \
と /
の両方が separator として認識されます。
参考:
This type supports a number of operations for inspecting a path, including breaking the path into its components (separated by / on Unix and by either / or \ on Windows), extracting the file name, determining whether the path is absolute, and so on.
relative or absolute
Path が相対パスか絶対パスかをチェックするために、 is_relative
, is_absolute
というメソッドが提供されています。
is_relative
の実装 は下記のとおりです。
is_relative
は単に is_absolute
の逆の結果を返すように実装されています。
!self.is_absolute()
is_absolute
の実装 は下記のとおりです。
is_absolute
は Unix か Windows によって判定の仕方が変わります。
(redox の場合も判定の仕方が違いますが、今回は省略。)
Unix の場合、 is_absolute
と has_root
の結果は同じで、パスが /
から始まれば絶対パスと判定されます。
Windows の場合、 prefix (C:
など)から始まるかつ prefix 以降が \
か /
から始まれば絶対パスと判定されます。
self.has_root() && (cfg!(unix) || self.prefix().is_some())
Path
どうしの比較
rust では 2つの struct がイコールであるかどうかの判定を PartialEq
trait で実装します。
Path
の PartialEq
の実装 は下記のとおりです。
components()
の内容を比較していることが分かります。
impl cmp::PartialEq for Path { fn eq(&self, other: &Path) -> bool { self.components().eq(other.components()) } }
components()
はパスを separator で区切ってできた Component
への iterator を返します。
ただし、区切る際に、連続する /
を無視する、始まり以外の .
を無視する、末尾の /
を無視するなどの処理が行われます。
したがって、以下の assertion はすべて true になります。
assert!(Path::new("a//b") == Path::new("a/b")); assert!(Path::new("a/./b") == Path::new("a/b")); assert!(Path::new("a/b/") == Path::new("a/b"));
一方で a/b/..
と a
はイコールとして扱われません。
これは、 a/b
が symlink である可能性があるからです。
assert!(Path::new("a/b/..") != Path::new("a"));
~
の扱い
~
は home ディレクトリとして展開されることはなく、 ~
という名前のパスとして扱われます。
例えば、 Path::new("~").is_dir()
は false
となります(current dir に ~
という名前のディレクトリがなければ)。
これは、 ~
は /home/user
などではなく、 $PWD/~
を指していることになるためです。
assert!(!Path::new("~").is_dir());
~
を home ディレクトリとして展開するには、 shellexpand などのライブラリを使うと良いです。