フルパスが指定されているかどうかを確認してください


104

指定されたパスがフルパスかどうかを確認する方法はありますか?今私はこれをやっています:

if (template.Contains(":\\")) //full path already given
{
}
else //calculate the path from local assembly
{
}

しかし、これをチェックするためのよりエレガントな方法がなければなりませんか?

回答:


141

使用してみSystem.IO.Path.IsPathRootedますか?true絶対パスの場合も戻ります。

System.IO.Path.IsPathRooted(@"c:\foo"); // true
System.IO.Path.IsPathRooted(@"\foo"); // true
System.IO.Path.IsPathRooted("foo"); // false

System.IO.Path.IsPathRooted(@"c:1\foo"); // surprisingly also true
System.IO.Path.GetFullPath(@"c:1\foo");// returns "[current working directory]\1\foo"

14
2番目の例が絶対パスになるのはなぜですか?
om471987

3
2番目のパスは絶対パスではありませんが、ルート化されています。先頭のスラッシュはシステムのルートを示します。
detaylor 2012

3
@SmirkinGherkinでは、ルートパスと絶対パスの違いは何ですか?
Jason Axelson 2013年

1
ファイルシステムへのアクセスを回避したり、無効な入力に対して例外をスローしたりすることの利点を維持しながら、フルパスを保証する別の方法については、私の回答(stackoverflow.com/a/35046453/704808)を参照してくださいIsPathRooted
2016年

1
@ daniel、IIRCは、パスがで使用される有効なパスである必要はないことを示すために含まれていましたが、IsPathRooted重要なものではありませんでした。GetFullPathラインは、パスを観察することができ、評価されるように含まれていた
detaylor

30
Path.IsPathRooted(path)
&& !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)

上記の条件:

  • ファイルシステムのアクセス許可は必要ありません
  • falseの形式pathが無効なほとんどの場合に(例外をスローするのではなく)を返します。
  • ボリュームが含まれているtrue場合pathにのみ返されます

したがって、OPが提示したようなシナリオでは、以前の回答の条件よりも適している可能性があります。上記の条件とは異なり:

  • path == System.IO.Path.GetFullPath(path)falseこれらのシナリオで戻るのではなく、例外をスローします。
    • 発信者には必要な権限がありません
    • システムは絶対パスを取得できませんでした
    • パスにボリューム識別子の一部ではないコロン( ":")が含まれています
    • 指定されたパス、ファイル名、またはその両方がシステム定義の最大長を超えています
  • System.IO.Path.IsPathRooted(path)単一のディレクトリ区切り文字で始まるtrue場合に返されますpath

最後に、上記の条件をラップし、残りの可能な例外を排除するメソッドを次に示します。

public static bool IsFullPath(string path) {
    return !String.IsNullOrWhiteSpace(path)
        && path.IndexOfAny(System.IO.Path.GetInvalidPathChars().ToArray()) == -1
        && Path.IsPathRooted(path)
        && !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal);
}

編集:EM0は、やのようなパスの奇妙なケースに対処する優れたコメントと代替回答をC:行いましたC:dir。このようなパスの処理方法を決定するには、MSDN-> Windowsデスクトップアプリケーション -> 開発 -> デスクトップテクノロジー -> データアクセスとストレージ -> ローカルファイルシステム - - > [ ファイル管理 ] - > [ ファイル管理について - > 、削除を作成し、ファイルの維持 - > ファイル、パス、および名前空間の命名 - > 完全修飾対相対パス

ファイルを操作するWindows API関数の場合、一部のAPIには完全修飾パスが必要ですが、ファイル名は多くの場合、現在のディレクトリを基準にしています。ファイル名が次のいずれかで始まらない場合、ファイル名は現在のディレクトリを基準にしています。

  • 常に2つのバックスラッシュ文字( "\")で始まる任意の形式のUNC名。詳細については、次のセクションを参照してください。
  • 「C:\」や「d:\」などのバックスラッシュ付きのディスク指定子。
  • 単一のバックスラッシュ。たとえば、「\ directory」または「\ file.txt」。これは、絶対パスとも呼ばれます。

ファイル名がディスク指定子のみで始まり、コロンの後のバックスラッシュではない場合、指定された文字を含むドライブ上の現在のディレクトリへの相対パスとして解釈されます。現在のディレクトリがルートディレクトリである場合とそうでない場合があるのは、そのディスクでの最新の「ディレクトリの変更」操作中に設定された内容によって異なります。この形式の例は次のとおりです。

  • 「C:tmp.txt」は、ドライブCの現在のディレクトリにある「tmp.txt」という名前のファイルを指します。
  • 「C:tempdir \ tmp.txt」は、ドライブCの現在のディレクトリのサブディレクトリにあるファイルを指します。

[...]


3
これが無効なパスに対してスローしないことが好きですが、「C:」や「C:dir」などのパスに対してtrueを返します。これらは、現在のディレクトリを使用してGetFullPathによって解決されます(絶対パスではありません)。これらに対してfalseを返す回答を投稿しました。
EM0

@ EM0-ありがとう!あなたはちょうど私に何かを教えました。:)
2017

15

試す

System.IO.Path.IsPathRooted(template)

ローカルパスだけでなくUNCパスでも機能します。

例えば

Path.IsPathRooted(@"\\MyServer\MyShare\MyDirectory")  // returns true
Path.IsPathRooted(@"C:\\MyDirectory")  // returns true

13

古い質問ですが、もう1つ該当する答えがあります。ボリュームがローカルパスに含まれていることを確認する必要がある場合は、次のようにSystem.IO.Path.GetFullPath()を使用できます。

if (template == System.IO.Path.GetFullPath(template))
{
    ; //template is full path including volume or full UNC path
}
else
{
    if (useCurrentPathAndVolume)
        template = System.IO.Path.GetFullPath(template);
    else
        template = Assembly.GetExecutingAssembly().Location
}

3
これは私が必要としたものであり、IsPathRooted 'が相対パス(必ずしも絶対パスではない)に対してtrueを返すため、元の質問に近いようです
ビットコーダー

GetFullPathファイルシステムにアクセスし、いくつかの例外をスローする可能性があります。フルパスを保証する別の方法については、私の回答(stackoverflow.com/a/35046453/704808)を参照してください。
2016年

11

weirの答えに基づいて構築すると、これは無効なパスに対してはスローされませんが、false「C:」、「C:dirname」、「\ path」などのパスに対しても戻ります。

public static bool IsFullPath(string path)
{
    if (string.IsNullOrWhiteSpace(path) || path.IndexOfAny(Path.GetInvalidPathChars()) != -1 || !Path.IsPathRooted(path))
        return false;

    string pathRoot = Path.GetPathRoot(path);
    if (pathRoot.Length <= 2 && pathRoot != "/") // Accepts X:\ and \\UNC\PATH, rejects empty string, \ and X:, but accepts / to support Linux
        return false;

    if (pathRoot[0] != '\\' || pathRoot[1] != '\\')
        return true; // Rooted and not a UNC path

    return pathRoot.Trim('\\').IndexOf('\\') != -1; // A UNC server name without a share name (e.g "\\NAME" or "\\NAME\") is invalid
}

これはWindowsとLinuxでは異なる結果を返すことに注意してください。たとえば、「/ path」はLinuxでは絶対値ですが、Windowsでは絶対値ではありません。

単体テスト:

[Test]
public void IsFullPath()
{
    bool isWindows = Environment.OSVersion.Platform.ToString().StartsWith("Win"); // .NET Framework
    // bool isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows); // .NET Core

    // These are full paths on Windows, but not on Linux
    TryIsFullPath(@"C:\dir\file.ext", isWindows);
    TryIsFullPath(@"C:\dir\", isWindows);
    TryIsFullPath(@"C:\dir", isWindows);
    TryIsFullPath(@"C:\", isWindows);
    TryIsFullPath(@"\\unc\share\dir\file.ext", isWindows);
    TryIsFullPath(@"\\unc\share", isWindows);

    // These are full paths on Linux, but not on Windows
    TryIsFullPath(@"/some/file", !isWindows);
    TryIsFullPath(@"/dir", !isWindows);
    TryIsFullPath(@"/", !isWindows);

    // Not full paths on either Windows or Linux
    TryIsFullPath(@"file.ext", false);
    TryIsFullPath(@"dir\file.ext", false);
    TryIsFullPath(@"\dir\file.ext", false);
    TryIsFullPath(@"C:", false);
    TryIsFullPath(@"C:dir\file.ext", false);
    TryIsFullPath(@"\dir", false); // An "absolute", but not "full" path

    // Invalid on both Windows and Linux
    TryIsFullPath(null, false, false);
    TryIsFullPath("", false, false);
    TryIsFullPath("   ", false, false);
    TryIsFullPath(@"C:\inval|d", false, false);
    TryIsFullPath(@"\\is_this_a_dir_or_a_hostname", false, false);
    TryIsFullPath(@"\\is_this_a_dir_or_a_hostname\", false, !isWindows);
    TryIsFullPath(@"\\is_this_a_dir_or_a_hostname\\", false, !isWindows);
}

private static void TryIsFullPath(string path, bool expectedIsFull, bool expectedIsValid = true)
{
    Assert.AreEqual(expectedIsFull, PathUtils.IsFullPath(path), "IsFullPath('" + path + "')");

    if (expectedIsFull)
    {
        Assert.AreEqual(path, Path.GetFullPath(path));
    }
    else if (expectedIsValid)
    {
        Assert.AreNotEqual(path, Path.GetFullPath(path));
    }
    else
    {
        Assert.That(() => Path.GetFullPath(path), Throws.Exception);
    }
}

いい物。私はという通知をしたmsdn.microsoft.com/en-us/library/windows/desktop/... Windows上のパスがあることを述べていない、それが始まる場合の相対例えば、単一のバックスラッシュ」、 『\ディレクトリ』または「\ファイル。txt"。これは、絶対パスとも呼ばれます。
2017

1
いい視点ね!私の用語が外れていたようです。私が「絶対パス」と言ったとき、MSが「フルパス」と呼んでいるものを本当に考えていました。名前を変更して、テストケースを追加しました。
EM0

1
この回答をありがとう、それは私を大いに助けました。ただし、\\ server \などのUNCパスの場合、メソッドはtrueを返しますが、Directory.Exists(path)(System.ArgumentException: 'UNCパスは次の形式である必要があります。 \\ server \ share。 ')
Carl

2
まだこれを使用していて、新しいエッジケースを見つけている人を見て嬉しい@Carlコードを更新し、それをテストした!
EM0

6

パスが完全修飾(MSDN)かどうかを確認するには:

public static bool IsPathFullyQualified(string path)
{
    var root = Path.GetPathRoot(path);
    return root.StartsWith(@"\\") || root.EndsWith(@"\");
}

これは、すでに提案されているものよりも少し単純ですが、などのドライブ相対パスに対しては依然としてfalseを返しますC:foo。そのロジックは「完全修飾」のMSDN定義に直接基づいており、私はそれが正しく動作しない例を見つけていません。


ただし、興味深いことに、.NET Core 2.1 Path.IsPathFullyQualifiedには、内部メソッドを使用する新しいメソッドがあるようです。PathInternal.IsPartiallyQualified(2018-04-17現在のリンクの場所は正確です)。

この投稿の子孫とより良い自己完結性のために、参考のために後者の実装を以下に示します。

internal static bool IsPartiallyQualified(ReadOnlySpan<char> path)
{
    if (path.Length < 2)
    {
        // It isn't fixed, it must be relative.  There is no way to specify a fixed
        // path with one character (or less).
        return true;
    }

    if (IsDirectorySeparator(path[0]))
    {
        // There is no valid way to specify a relative path with two initial slashes or
        // \? as ? isn't valid for drive relative paths and \??\ is equivalent to \\?\
        return !(path[1] == '?' || IsDirectorySeparator(path[1]));
    }

    // The only way to specify a fixed path that doesn't begin with two slashes
    // is the drive, colon, slash format- i.e. C:\
    return !((path.Length >= 3)
        && (path[1] == VolumeSeparatorChar)
        && IsDirectorySeparator(path[2])
        // To match old behavior we'll check the drive character for validity as the path is technically
        // not qualified if you don't have a valid drive. "=:\" is the "=" file's default data stream.
        && IsValidDriveChar(path[0]));
}

4

これは私が使用するソリューションです

public static bool IsFullPath(string path)
{
    try
    {
        return Path.GetFullPath(path) == path;
    }
    catch
    {
        return false;
    }
}

次のように機能します。

IsFullPath(@"c:\foo"); // true
IsFullPath(@"C:\foo"); // true
IsFullPath(@"c:\foo\"); // true
IsFullPath(@"c:/foo"); // false
IsFullPath(@"\foo"); // false
IsFullPath(@"foo"); // false
IsFullPath(@"c:1\foo\"); // false

とても興味深い!たとえば、それは壊れやすいので、スラッシュのタイプと一致する必要がありますが、これには約束があります。
Nicholas Petersen

次のパスに対して誤った結果が返されます。C:\foo\..\fooまたはC:\foo\.\.\.
sergtk

1

次の関数を呼び出します。

Path.IsPathFullyQualified(@"c:\foo")

MSDN doc:Path.IsPathFullyQualifiedメソッド

MSDNドキュメントからの有用な引用は次のとおりです。

このメソッドは、代替ディレクトリ区切り記号を使用するパスを処理します。ルート化されたパス(IsPathRooted(String))が相対パスではないと仮定することはよくある間違いです。たとえば、「C:a」はドライブ相対です。つまり、C:の現在のディレクトリに対して解決されます(ルート付きですが、相対)。「C:\ a」はルートではなく、相対パスです。つまり、現在のディレクトリはパスの変更に使用されません。


0

フルパスで何を意味するのかはよくわかりません(例から、ルート以降は非相対を意味するものと想定しています)。まあ、Pathクラスを使用して、物理ファイルシステムパスの操作を支援できます。あなたはほとんどの場合に備えて。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.