最終更新日時(UTC):
が更新

履歴 編集

function
<filesystem>

std::filesystem::path::lexically_normal(C++17)

path lexically_normal() const;

概要

文字列レベルで正規化する。

この関数は、ファイルシステムを介することのないパスの正規化を行う。そのため、親ディレクトリの参照を解決できない場合がある。ファイルシステムを介した正規化を行う場合は、std::filesystem::canonical()std::filesystem::weakly_canonical()関数を使用すること。

戻り値

*thisが保持するパスを正規化したパスのコピーを返す。

パスの正規化は、以下のことを行う:

  1. パスが空であれば、以降なにもしない
  2. "." (ドットx1) ファイル名と、それに続くディレクトリ区切り文字を削除する (a/b/./c => a/b/ca/b/./ => a/b/)
  3. ディレクトリ区切り文字 + ".." (ドットx2) の直前にある非 ".." ファイル名と、その ".." および続くディレクトリ区切り文字を削除する (a/b/.. => a/)
    • 親ディレクトリがなくなるまで繰り返す。ルートディレクトリに対する..は、ルートディレクトリとなる (/.. => /)
  4. 最後のファイル名が ".." である場合、末尾のディレクトリ区切り文字を削除する
  5. 正規化の結果として空のパスになった場合、"." を追加する

#include <cassert>
#include <filesystem>

namespace fs = std::filesystem;

int main()
{
  // 自身のディレクトリを表す "./" を削除
  // 親ディレクトリを指す ".." があるため、 "bar/.." を削除
  assert(fs::path("foo/./bar/..").lexically_normal().generic_string() == "foo/");

  // ひとつ前の例とほぼ同じだが、 ./// のようにディレクトリ区切り文字がいくつあっても、
  // ひとつと等価の意味を持つため、まとめて削除される
  assert(fs::path("foo/.///bar/../").lexically_normal().generic_string() == "foo/");

  // (ファイルシステムを介することのない) 文字列だけでは親ディレクトリを解決できないため、
  // 正規化してもそのまま。
  // 末尾のディレクトリ区切り文字だけ削除される
  assert(fs::path("../../").lexically_normal().generic_string() == "../..");

  // 正規化の結果として空文字列になるため、 "." のみのパスとなる
  assert(fs::path("foo/..").lexically_normal().generic_string() == ".");
}

出力

バージョン

言語

  • C++17

処理系