131

I am just wondering: I am looking for a way to validate if a given path is valid. (Note: I do not want to check if a file is existing! I only want to proof the validity of the path - So if a file could possibly exists at the location).

Problem is, I can't find anything in the .Net API. Due to the many formats and locations that Windows supports, I'd rather use something MS-native.

Since the function should be able to check against:

  • Relative Paths (./)
  • Absolute Paths (c:\tmp)
  • UNC-Pathes (\some-pc\c$)
  • NTFS-Limitations like the full path 1024 chars - If I am not mistaken exceeding the path will make a file inaccessible for many internal Windows functions. Renaming it with Explorer still works
  • Volume GUID Paths : "\?\Volume{GUID}\somefile.foo

Does anyone have a function like this?

InteXX
  • 6,135
  • 6
  • 43
  • 80
Tobias Boschek
  • 2,158
  • 3
  • 18
  • 22
  • possible duplicate of [How check if given string is legal (allowed) file name under Windows?](http://stackoverflow.com/questions/62771/how-check-if-given-string-is-legal-allowed-file-name-under-windows) – nawfal Jun 05 '13 at 11:43

12 Answers12

66

Try Uri.IsWellFormedUriString():

  • The string is not correctly escaped.

      http://www.example.com/path???/file name
    
  • The string is an absolute Uri that represents an implicit file Uri.

      c:\\directory\filename
    
  • The string is an absolute URI that is missing a slash before the path.

      file://c:/directory/filename
    
  • The string contains unescaped backslashes even if they are treated as forward slashes.

      http:\\host/path/file
    
  • The string represents a hierarchical absolute Uri and does not contain "://".

      www.example.com/path/file
    
  • The parser for the Uri.Scheme indicates that the original string was not well-formed.

      The example depends on the scheme of the URI.
    
Ivan Ivković
  • 417
  • 3
  • 14
abatishchev
  • 98,240
  • 88
  • 296
  • 433
  • This sounds very promising... I take a closer look at it! I'll drop a line after I have evaluated if the method serves my purpose! Thanks abatishchev – Tobias Boschek Jun 01 '11 at 12:45
  • 12
    This returns false for `@"foo\bar\baz"`, which is a perfectly valid relative path... – Thomas Levesque Oct 18 '12 at 08:26
  • 5
    Thomas: What UriKind did you specify? You can use Absolute, Relative or AbsoluteOrRelative. – Dan Gøran Lunde Feb 09 '13 at 10:38
  • 3
    Even with UriKind as Relative or AbsoluteOrRelative it didn't work for relative paths like Thomas mentioned. I ended up using Patko's answer instead & it works for my purposes. – JohnnyM Apr 16 '14 at 20:15
  • 1
    I found that a path such as \\computerName\Dir Name With Spaces\fileName throws an exception when using IsWellFormedUriString (contrary to my initial expectation), because the spaces aren't properly encoded. I found that I could just use the Uri(string) constructor as my validation, thereby, not having to properly encode the string before validating. – quintessential5 Jul 15 '14 at 23:37
  • Does not work with a simple path like "\\myserver\mypath" with releative or absolute uri kind. – AH. Sep 15 '15 at 12:14
  • 1
    This doesn't work for all this exemples. https://msdn.microsoft.com/en-us/library/system.uri.iswellformeduristring(v=vs.110).aspx The documentation say : "The string is considered poorly formed, causing the method to return false, if any of the following conditions occur : The string is not correctly escaped. http://www.contoso.com/path???/file name The string is an absolute Uri that represents an implicit file Uri. c:\\directory\filename …" – Xav987 Jan 19 '17 at 15:46
  • 4
    Returns false on a perfectly fine file path. – Evgeni Petrov Mar 06 '17 at 15:55
  • Answer says `IsWellFormedUriString` but links to `IsWellFormedOriginalString`. Though the page seems to indicate the former has special behavior with .Net 4.5+, I believe the main difference is that one is static and one is an instance method. – Chris Apr 26 '18 at 14:05
31

Or use the FileInfo as suggested in In C# check that filename is possibly valid (not that it exists).

Community
  • 1
  • 1
Patko
  • 4,365
  • 1
  • 32
  • 27
  • 1
    Using the solution posted by "LamdaComplex", on the same thread, seems more accurate : http://stackoverflow.com/a/11636052/2546739 – Xav987 Jan 19 '17 at 16:28
13

I haven't had any problems with the code below. (Relative paths must start with '/' or '\').

private bool IsValidPath(string path, bool allowRelativePaths = false)
{
    bool isValid = true;

    try
    {
        string fullPath = Path.GetFullPath(path);

        if (allowRelativePaths)
        {
            isValid = Path.IsPathRooted(path);
        }
        else
        {
            string root = Path.GetPathRoot(path);
            isValid = string.IsNullOrEmpty(root.Trim(new char[] { '\\', '/' })) == false;
        }
    }
    catch(Exception ex)
    {
        isValid = false;
    }

    return isValid;
}

For example these would return false:

IsValidPath("C:/abc*d");
IsValidPath("C:/abc?d");
IsValidPath("C:/abc\"d");
IsValidPath("C:/abc<d");
IsValidPath("C:/abc>d");
IsValidPath("C:/abc|d");
IsValidPath("C:/abc:d");
IsValidPath("");
IsValidPath("./abc");
IsValidPath("./abc", true);
IsValidPath("/abc");
IsValidPath("abc");
IsValidPath("abc", true);

And these would return true:

IsValidPath(@"C:\\abc");
IsValidPath(@"F:\FILES\");
IsValidPath(@"C:\\abc.docx\\defg.docx");
IsValidPath(@"C:/abc/defg");
IsValidPath(@"C:\\\//\/\\/\\\/abc/\/\/\/\///\\\//\defg");
IsValidPath(@"C:/abc/def~`!@#$%^&()_-+={[}];',.g");
IsValidPath(@"C:\\\\\abc////////defg");
IsValidPath(@"/abc", true);
IsValidPath(@"\abc", true);
Dao Seeker
  • 214
  • 2
  • 11
6
private bool IsValidPath(string path)
{
    Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");
    if (!driveCheck.IsMatch(path.Substring(0, 3))) return false;
    string strTheseAreInvalidFileNameChars = new string(Path.GetInvalidPathChars());
    strTheseAreInvalidFileNameChars += @":/?*" + "\"";
    Regex containsABadCharacter = new Regex("[" + Regex.Escape(strTheseAreInvalidFileNameChars) + "]");
    if (containsABadCharacter.IsMatch(path.Substring(3, path.Length - 3)))
        return false;

    DirectoryInfo dir = new DirectoryInfo(Path.GetFullPath(path));
    if (!dir.Exists)
        dir.Create();
    return true;
}
Ghasem
  • 14,455
  • 21
  • 138
  • 171
  • 11
    Creating a folder is a nasty side effect for a boolean that you think is going to just check a string for you. – HackSlash Nov 30 '20 at 22:36
6

You can try this code:

try
{
  Path.GetDirectoryName(myPath);
}
catch
{
  // Path is not valid
}

I'm not sure it covers all the cases...

Nimrod
  • 153
  • 3
  • 8
4

There are plenty of good solutions in here, but as none of then check if the path is rooted in an existing drive here's another one:

private bool IsValidPath(string path)
{
    // Check if the path is rooted in a driver
    if (path.Length < 3) return false;
    Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");
    if (!driveCheck.IsMatch(path.Substring(0, 3))) return false;

    // Check if such driver exists
    IEnumerable<string> allMachineDrivers = DriveInfo.GetDrives().Select(drive => drive.Name);
    if (!allMachineDrivers.Contains(path.Substring(0, 3))) return false;

    // Check if the rest of the path is valid
    string InvalidFileNameChars = new string(Path.GetInvalidPathChars());
    InvalidFileNameChars += @":/?*" + "\"";
    Regex containsABadCharacter = new Regex("[" + Regex.Escape(InvalidFileNameChars) + "]");
    if (containsABadCharacter.IsMatch(path.Substring(3, path.Length - 3)))
        return false;
    if (path[path.Length - 1] == '.') return false;

    return true;
}

This solution does not take relative paths into account.

Gark Garcia
  • 450
  • 6
  • 14
  • 2
    It passes my tests, just missing the null check.. it could be added at first condition `if (path == null || path.Length < 3) return false;` – Muhammad Sulaiman Jul 19 '22 at 11:14
  • 1
    another thing is, ```d:\folder1\``` is considered not valid path due to `d` being small-letter, I solved it by adding `path = path?.ToUpper();` at the beginning of the function.. – Muhammad Sulaiman Jul 19 '22 at 11:32
1

The closest I have come is by trying to create it, and seeing if it succeeds.

Martijn
  • 11,964
  • 12
  • 50
  • 96
1

Get the invalid chars from System.IO.Path.GetInvalidPathChars(); and check if your string (Directory path) contains those or not.

Umesh CHILAKA
  • 1,466
  • 14
  • 25
  • 4
    This isn't entirely valid. "C:\new.folder" is valid while "C:\newfolder." is not. '.' is a valid character for a paths/filenames, but not at the end of the uri. – claudekennilol Mar 07 '13 at 16:13
1

this accepts a path that could equate to a valid relative path too

string path = "yourPath";
bool pathIsValid = null;
try
{ 
    Path.GetFullPath(path);
    pathIsValid = true;
}
catch
{
    pathIsValid = false;
}
ultramegaok
  • 131
  • 5
-1
private bool IsValidPath(string path)
{
    Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");

    if (string.IsNullOrWhiteSpace(path) || path.Length < 3)
    {
        return false;
    }

    if (!driveCheck.IsMatch(path.Substring(0, 3)))
    {
        return false;
    }

    var x1 = (path.Substring(3, path.Length - 3));
    string strTheseAreInvalidFileNameChars = new string(Path.GetInvalidPathChars());
    strTheseAreInvalidFileNameChars += @":?*";
    Regex containsABadCharacter = new Regex("[" + Regex.Escape(strTheseAreInvalidFileNameChars) + "]");

    if (containsABadCharacter.IsMatch(path.Substring(3, path.Length - 3)))
    {
        return false;
    }

    var driveLetterWithColonAndSlash = Path.GetPathRoot(path);

    if (!DriveInfo.GetDrives().Any(x => x.Name == driveLetterWithColonAndSlash))
    {
        return false;
    }

    return true;
}
krlzlx
  • 5,752
  • 14
  • 47
  • 55
-4

You could try using Path.IsPathRooted() in combination with Path.GetInvalidFileNameChars() to make sure the path is half-way okay.

-4

Directory.Exists?

markpsmith
  • 4,860
  • 2
  • 33
  • 62