전체 경로가 제공되었는지 확인하십시오.


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
두 번째 예는 어떻게 절대 경로가됩니까?
om471987

4
두 번째 경로는 절대적이지는 않지만 뿌리가 있습니다. 선행 슬래시는 시스템의 루트를 나타냅니다.
detaylor

3
@SmirkinGherkin 그래서 루트 경로와 절대 경로의 차이점은 무엇입니까?
Jason Axelson 2013 년

1
다음 의 장점을 유지하면서 전체 경로를 보장하는 대안 은 내 대답 ( stackoverflow.com/a/35046453/704808 )을 참조하십시오 IsPathRooted. 파일 시스템 액세스 방지 또는 잘못된 입력에 대한 예외 발생.
weir

1
@daniel, IIRC이 경로에 사용할 수있는 유효한 경로 필요하지 않은 것을 보여주기 위해 포함되었습니다 IsPathRooted, 그것은 확실히 중요한 아무것도하지 않았다. GetFullPath라인은 경로를 관찰 할 수있는 평가되고 너무 포함되었다
detaylor

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

위의 조건 :

  • 파일 시스템 권한이 필요하지 않습니다.
  • false형식 path이 유효하지 않은 대부분의 경우를 반환합니다 (예외를 던지는 대신).
  • 볼륨 truepath포함 된 경우에만 반환

OP가 제시 한 시나리오와 같은 시나리오에서는 이전 답변의 조건보다 더 적합 할 수 있습니다. 위의 조건과 달리 :

  • path == System.IO.Path.GetFullPath(path)false다음 시나리오에서 반환하지 않고 예외를 throw합니다 .
    • 발신자에게 필요한 권한이 없습니다.
    • 시스템이 절대 경로를 검색 할 수 없습니다.
    • 경로에 볼륨 식별자의 일부가 아닌 콜론 ( ":")이 있습니다.
    • 지정된 경로, 파일 이름 또는 둘 다 시스템 정의 최대 길이를 초과합니다.
  • 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에는 완전한 경로가 필요합니다. 다음 중 하나로 시작하지 않는 파일 이름은 현재 디렉토리에 상대적입니다.

  • 항상 두 개의 백 슬래시 문자 ( "\")로 시작하는 모든 형식의 UNC 이름. 자세한 내용은 다음 섹션을 참조하십시오.
  • 백 슬래시가있는 디스크 지정자 (예 : "C : \"또는 "d : \").
  • 단일 백 슬래시 (예 : "\ directory"또는 "\ file.txt") 이것은 절대 경로라고도합니다.

파일 이름이 디스크 지정 자로 만 시작되고 콜론 뒤의 백 슬래시가 아닌 경우 지정된 문자가있는 드라이브의 현재 디렉토리에 대한 상대 경로로 해석됩니다. 현재 디렉토리는 해당 디스크에서 가장 최근의 "디렉토리 변경"작업 중에 설정된 항목에 따라 루트 디렉토리 일 수도 있고 아닐 수도 있습니다. 이 형식의 예는 다음과 같습니다.

  • "C : tmp.txt"는 C 드라이브의 현재 디렉토리에있는 "tmp.txt"라는 파일을 나타냅니다.
  • "C : tempdir \ tmp.txt"는 C 드라이브의 현재 디렉터리에 대한 하위 디렉터리의 파일을 나타냅니다.

[...]


3
나는 이것이 잘못된 경로에 대해 던지지 않는 것이 좋지만, 현재 디렉터리를 사용하여 GetFullPath에 의해 해결되는 "C :"및 "C : dir"과 같은 경로에 대해 true를 반환하므로 절대적이지 않습니다. 이에 대해 거짓을 반환하는 답변을 게시했습니다.
EM0

@ EM0-감사합니다! 당신은 나에게 뭔가를 가르쳤습니다. :)
위어

15

시험

System.IO.Path.IsPathRooted(template)

UNC 경로 및 로컬 경로에 대해 작동합니다.

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

13

이전 질문이지만 적용 가능한 답변이 하나 더 있습니다. 볼륨이 로컬 경로에 포함되어 있는지 확인해야하는 경우 다음과 같이 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를 반환하기 때문에 원래 질문에 더 가깝게 보입니다
bitcoder

GetFullPath파일 시스템에 액세스하고 여러 가능한 예외를 발생시킬 수 있습니다. 여전히 전체 경로를 보장하는 대안 은 내 대답 ( stackoverflow.com/a/35046453/704808 )을 참조하십시오 .
weir

11

바탕 위어 도 반환이 유효하지 않은 경로에 대한 던져하지 않지만 '의 대답을 false같은 경로는 "C :", "C : dirname이"와 "\ 경로를".

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 "입니다. 이것은 절대 경로라고도합니다. '
weir

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(@"\");
}

이미 제안 된 것보다 조금 더 간단하며 .NET과 같은 드라이브 상대 경로에 대해 여전히 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 2013

다음 경로에 대해 잘못된 결과를 반환합니다. C:\foo\..\foo또는C:\foo\.\.\.
sergtk

1

다음 함수를 호출하십시오.

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

MSDN 문서 : Path.IsPathFullyQualified 메서드

MSDN 문서의 유용한 인용은 다음과 같습니다.

이 메서드는 대체 디렉터리 구분 기호를 사용하는 경로를 처리합니다. 루트 경로 ( IsPathRooted (String) )가 상대적이지 않다고 가정하는 것은 자주 실수 입니다. 예를 들어, "C : a"는 드라이브 상대입니다. 즉, C :의 현재 디렉터리에 대해 확인됩니다 (루팅되었지만 상대). "C : \ a"는 루트이며 상대적이 아닙니다. 즉, 현재 디렉토리가 경로를 수정하는 데 사용되지 않습니다.


0

전체 경로가 무엇을 의미하는지 잘 모르겠습니다 (예제에서 루트에서 비 상대적이라는 것을 의미한다고 가정하더라도) 음, Path 클래스를 사용하여 실제 파일 시스템 경로로 작업 할 수 있습니다. 대부분의 경우에 당신.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.