ChatGPT解决这个技术问题 Extra ChatGPT

Better way to check if a Path is a File or a Directory?

I am processing a TreeView of directories and files. A user can select either a file or a directory and then do something with it. This requires me to have a method which performs different actions based on the user's selection.

At the moment I am doing something like this to determine whether the path is a file or a directory:

bool bIsFile = false;
bool bIsDirectory = false;

try
{
    string[] subfolders = Directory.GetDirectories(strFilePath);

    bIsDirectory = true;
    bIsFile = false;
}
catch(System.IO.IOException)
{
    bIsFolder = false;
    bIsFile = true;
}

I cannot help to feel that there is a better way to do this! I was hoping to find a standard .NET method to handle this, but I haven't been able to do so. Does such a method exist, and if not, what is the most straightforward means to determine whether a path is a file or directory?

Can someone edit the question title to specify "existing" file/directory? All of the answers apply to a path for a file/directory that is on disk.
@jberger please refer to my answer below. I found a way to accomplish this for paths of files/folders which may or may not exist.
How are you populating this treeview? How are you getting the path out of it?

R
Raz Luvaton

From How to tell if path is file or directory:

// get the file attributes for file or directory
FileAttributes attr = File.GetAttributes(@"c:\Temp");

//detect whether its a directory or file
if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
    MessageBox.Show("Its a directory");
else
    MessageBox.Show("Its a file");

Update for .NET 4.0+

Per the comments below, if you are on .NET 4.0 or later (and maximum performance is not critical) you can write the code in a cleaner way:

// get the file attributes for file or directory
FileAttributes attr = File.GetAttributes(@"c:\Temp");

if (attr.HasFlag(FileAttributes.Directory))
    MessageBox.Show("Its a directory");
else
    MessageBox.Show("Its a file");

+1 This is the better approach and is significantly faster than the solution I have proposed.
@KeyMs92 Its bitwise math. Basically, attr is some binary value with one bit meaning "this is a directory". The bitwise and & operator will return a binary value where only the bits that are on (1) in both the operands are turned on. In this case doing a bitwise and operation against attr and the FileAttributes.Directory value will return the value of FileAttributes.Directory if the Directory file attribute bit is turned on. See en.wikipedia.org/wiki/Bitwise_operation for a better explanation.
@jberger If the path doesn't exist then it's ambiguous whether C:\Temp refers to a directory called Temp or a file called Temp. What's the code meant to do?
@Key: After .NET 4.0, attr.HasFlag(FileAttributes.Directory) can be used instead.
@ŞafakGür: Don't do this inside a time sensitive loop. attr.HasFlag() is slow as hell and uses Reflection for each call
l
llamaoo7

How about using these?

File.Exists();
Directory.Exists();

This also has the advantage of not throwing an exception on an invalid path, unlike File.GetAttributes().
I use Long Path library from BCL bcl.codeplex.com/… in my project so there's no way to get file attributes but calling Exist is a nice workaround.
@jberger I would expect it to NOT work for paths to non-existent files/folders. File.Exists("c:\\temp\\nonexistant.txt") should return false, as it does.
If you are worried about non-existent files/folders try this public static bool? IsDirectory(string path){ if (Directory.Exists(path)) return true; // is a directory else if (File.Exists(path)) return false; // is a file else return null; // is a nothing }
More details on this are at msdn.microsoft.com/en-us/library/…
n
nawfal

With only this line you can get if a path is a directory or a file:

File.GetAttributes(data.Path).HasFlag(FileAttributes.Directory)

Mind you need at least .NET 4.0 for this. Also this will explode if path is not a valid path.
Use a FileInfo object to check if the path exists: FileInfo pFinfo = new FileInfo(FList[0]); if (pFinfo.Exists) { if (File.GetAttributes(FList[0]).HasFlag(FileAttributes.Directory)) {} }. This one works for me.
If you've already created a FileInfo object and are using the instance's Exists property, why not access its Attributes property instead of using the static File.GetAttributes() method?
R
Ronnie Overby

Here's mine:

    bool IsPathDirectory(string path)
    {
        if (path == null) throw new ArgumentNullException("path");
        path = path.Trim();

        if (Directory.Exists(path)) 
            return true;

        if (File.Exists(path)) 
            return false;

        // neither file nor directory exists. guess intention

        // if has trailing slash then it's a directory
        if (new[] {"\\", "/"}.Any(x => path.EndsWith(x)))
            return true; // ends with slash

        // if has extension then its a file; directory otherwise
        return string.IsNullOrWhiteSpace(Path.GetExtension(path));
    }

It's similar to others' answers but not exactly the same.


Technically you should use Path.DirectorySeparatorChar and Path.AltDirectorySeparatorChar
This idea to guess intent is interesting. IMHO better to split into two methods. Method One does the Existence tests, returning a nullable boolean. If caller then wants the "guess" part, on a null result from One, then call Method Two, which does the guessing.
I'd rewrite this to to return a tuple with whether it guessed or not.
"if has extension then its a file" - this is not true. A file doesnt have to have an extension (even in windows) and a directory can have a "extension". For example this can be a file or a directory: "C:\New folder.log"
@bytedev I know that, but at that point in the function, the code is guessing intention. There's even a comment saying so. Most files have an extension. Most directories don't.
C
Community

As an alternative to Directory.Exists(), you can use the File.GetAttributes() method to get the attributes of a file or a directory, so you could create a helper method like this:

private static bool IsDirectory(string path)
{
    System.IO.FileAttributes fa = System.IO.File.GetAttributes(path);
    return (fa & FileAttributes.Directory) != 0;
}

You could also consider adding an object to the tag property of the TreeView control when populating the control that contains additional metadata for the item. For instance, you could add a FileInfo object for files and a DirectoryInfo object for directories and then test for the item type in the tag property to save making additional system calls to get that data when clicking on the item.


how is this different than the other answer
Rather than that horrible block of logic, try isDirectory = (fa & FileAttributes.Directory) != 0);
C
Community

After combining the suggestions from the other answers, I realized I came up with about the same thing as Ronnie Overby's answer. Here are some tests to point out some things to think about:

folders can have "extensions": C:\Temp\folder_with.dot files cannot end with a directory separator (slash) There are technically two directory separators which are platform specific -- i.e. may or may not be slashes (Path.DirectorySeparatorChar and Path.AltDirectorySeparatorChar)

Tests (Linqpad)

var paths = new[] {
    // exists
    @"C:\Temp\dir_test\folder_is_a_dir",
    @"C:\Temp\dir_test\is_a_dir_trailing_slash\",
    @"C:\Temp\dir_test\existing_folder_with.ext",
    @"C:\Temp\dir_test\file_thats_not_a_dir",
    @"C:\Temp\dir_test\notadir.txt",
    // doesn't exist
    @"C:\Temp\dir_test\dne_folder_is_a_dir",
    @"C:\Temp\dir_test\dne_folder_trailing_slash\",
    @"C:\Temp\dir_test\non_existing_folder_with.ext",
    @"C:\Temp\dir_test\dne_file_thats_not_a_dir",
    @"C:\Temp\dir_test\dne_notadir.txt",        
};

foreach(var path in paths) {
    IsFolder(path/*, false*/).Dump(path);
}

Results

C:\Temp\dir_test\folder_is_a_dir
  True 
C:\Temp\dir_test\is_a_dir_trailing_slash\
  True 
C:\Temp\dir_test\existing_folder_with.ext
  True 
C:\Temp\dir_test\file_thats_not_a_dir
  False 
C:\Temp\dir_test\notadir.txt
  False 
C:\Temp\dir_test\dne_folder_is_a_dir
  True 
C:\Temp\dir_test\dne_folder_trailing_slash\
  True 
C:\Temp\dir_test\non_existing_folder_with.ext
  False (this is the weird one)
C:\Temp\dir_test\dne_file_thats_not_a_dir
  True 
C:\Temp\dir_test\dne_notadir.txt
  False 

Method

/// <summary>
/// Whether the <paramref name="path"/> is a folder (existing or not); 
/// optionally assume that if it doesn't "look like" a file then it's a directory.
/// </summary>
/// <param name="path">Path to check</param>
/// <param name="assumeDneLookAlike">If the <paramref name="path"/> doesn't exist, does it at least look like a directory name?  As in, it doesn't look like a file.</param>
/// <returns><c>True</c> if a folder/directory, <c>false</c> if not.</returns>
public static bool IsFolder(string path, bool assumeDneLookAlike = true)
{
    // https://stackoverflow.com/questions/1395205/better-way-to-check-if-path-is-a-file-or-a-directory
    // turns out to be about the same as https://stackoverflow.com/a/19596821/1037948

    // check in order of verisimilitude

    // exists or ends with a directory separator -- files cannot end with directory separator, right?
    if (Directory.Exists(path)
        // use system values rather than assume slashes
        || path.EndsWith("" + Path.DirectorySeparatorChar)
        || path.EndsWith("" + Path.AltDirectorySeparatorChar))
        return true;

    // if we know for sure that it's an actual file...
    if (File.Exists(path))
        return false;

    // if it has an extension it should be a file, so vice versa
    // although technically directories can have extensions...
    if (!Path.HasExtension(path) && assumeDneLookAlike)
        return true;

    // only works for existing files, kinda redundant with `.Exists` above
    //if( File.GetAttributes(path).HasFlag(FileAttributes.Directory) ) ...; 

    // no idea -- could return an 'indeterminate' value (nullable bool)
    // or assume that if we don't know then it's not a folder
    return false;
}

Path.DirectorySeparatorChar.ToString() instead of string concat with ""?
@GoneCoding probably; at the time I had been working with a bunch of nullable properties so I got in the habit of "concat with empty string" rather than worry about checking for null. You could also do new String(Path.DirectorySeparatorChar, 1) as that's what ToString does, if you wanted to get really optimized.
H
HAL9000

This was the best I could come up with given the behavior of the Exists and Attributes properties:

using System.IO;

public static class FileSystemInfoExtensions
{
    /// <summary>
    /// Checks whether a FileInfo or DirectoryInfo object is a directory, or intended to be a directory.
    /// </summary>
    /// <param name="fileSystemInfo"></param>
    /// <returns></returns>
    public static bool IsDirectory(this FileSystemInfo fileSystemInfo)
    {
        if (fileSystemInfo == null)
        {
            return false;
        }

        if ((int)fileSystemInfo.Attributes != -1)
        {
            // if attributes are initialized check the directory flag
            return fileSystemInfo.Attributes.HasFlag(FileAttributes.Directory);
        }

        // If we get here the file probably doesn't exist yet.  The best we can do is 
        // try to judge intent.  Because directories can have extensions and files
        // can lack them, we can't rely on filename.
        // 
        // We can reasonably assume that if the path doesn't exist yet and 
        // FileSystemInfo is a DirectoryInfo, a directory is intended.  FileInfo can 
        // make a directory, but it would be a bizarre code path.

        return fileSystemInfo is DirectoryInfo;
    }
}

Here's how it tests out:

    [TestMethod]
    public void IsDirectoryTest()
    {
        // non-existing file, FileAttributes not conclusive, rely on type of FileSystemInfo
        const string nonExistentFile = @"C:\TotallyFakeFile.exe";

        var nonExistentFileDirectoryInfo = new DirectoryInfo(nonExistentFile);
        Assert.IsTrue(nonExistentFileDirectoryInfo.IsDirectory());

        var nonExistentFileFileInfo = new FileInfo(nonExistentFile);
        Assert.IsFalse(nonExistentFileFileInfo.IsDirectory());

        // non-existing directory, FileAttributes not conclusive, rely on type of FileSystemInfo
        const string nonExistentDirectory = @"C:\FakeDirectory";

        var nonExistentDirectoryInfo = new DirectoryInfo(nonExistentDirectory);
        Assert.IsTrue(nonExistentDirectoryInfo.IsDirectory());

        var nonExistentFileInfo = new FileInfo(nonExistentDirectory);
        Assert.IsFalse(nonExistentFileInfo.IsDirectory());

        // Existing, rely on FileAttributes
        const string existingDirectory = @"C:\Windows";

        var existingDirectoryInfo = new DirectoryInfo(existingDirectory);
        Assert.IsTrue(existingDirectoryInfo.IsDirectory());

        var existingDirectoryFileInfo = new FileInfo(existingDirectory);
        Assert.IsTrue(existingDirectoryFileInfo.IsDirectory());

        // Existing, rely on FileAttributes
        const string existingFile = @"C:\Windows\notepad.exe";

        var existingFileDirectoryInfo = new DirectoryInfo(existingFile);
        Assert.IsFalse(existingFileDirectoryInfo.IsDirectory());

        var existingFileFileInfo = new FileInfo(existingFile);
        Assert.IsFalse(existingFileFileInfo.IsDirectory());
    }

B
Bo Persson

Here's what we use:

using System;

using System.IO;

namespace crmachine.CommonClasses
{

  public static class CRMPath
  {

    public static bool IsDirectory(string path)
    {
      if (path == null)
      {
        throw new ArgumentNullException("path");
      }

      string reason;
      if (!IsValidPathString(path, out reason))
      {
        throw new ArgumentException(reason);
      }

      if (!(Directory.Exists(path) || File.Exists(path)))
      {
        throw new InvalidOperationException(string.Format("Could not find a part of the path '{0}'",path));
      }

      return (new System.IO.FileInfo(path).Attributes & FileAttributes.Directory) == FileAttributes.Directory;
    } 

    public static bool IsValidPathString(string pathStringToTest, out string reasonForError)
    {
      reasonForError = "";
      if (string.IsNullOrWhiteSpace(pathStringToTest))
      {
        reasonForError = "Path is Null or Whitespace.";
        return false;
      }
      if (pathStringToTest.Length > CRMConst.MAXPATH) // MAXPATH == 260
      {
        reasonForError = "Length of path exceeds MAXPATH.";
        return false;
      }
      if (PathContainsInvalidCharacters(pathStringToTest))
      {
        reasonForError = "Path contains invalid path characters.";
        return false;
      }
      if (pathStringToTest == ":")
      {
        reasonForError = "Path consists of only a volume designator.";
        return false;
      }
      if (pathStringToTest[0] == ':')
      {
        reasonForError = "Path begins with a volume designator.";
        return false;
      }

      if (pathStringToTest.Contains(":") && pathStringToTest.IndexOf(':') != 1)
      {
        reasonForError = "Path contains a volume designator that is not part of a drive label.";
        return false;
      }
      return true;
    }

    public static bool PathContainsInvalidCharacters(string path)
    {
      if (path == null)
      {
        throw new ArgumentNullException("path");
      }

      bool containedInvalidCharacters = false;

      for (int i = 0; i < path.Length; i++)
      {
        int n = path[i];
        if (
            (n == 0x22) || // "
            (n == 0x3c) || // <
            (n == 0x3e) || // >
            (n == 0x7c) || // |
            (n  < 0x20)    // the control characters
          )
        {
          containedInvalidCharacters = true;
        }
      }

      return containedInvalidCharacters;
    }


    public static bool FilenameContainsInvalidCharacters(string filename)
    {
      if (filename == null)
      {
        throw new ArgumentNullException("filename");
      }

      bool containedInvalidCharacters = false;

      for (int i = 0; i < filename.Length; i++)
      {
        int n = filename[i];
        if (
            (n == 0x22) || // "
            (n == 0x3c) || // <
            (n == 0x3e) || // >
            (n == 0x7c) || // |
            (n == 0x3a) || // : 
            (n == 0x2a) || // * 
            (n == 0x3f) || // ? 
            (n == 0x5c) || // \ 
            (n == 0x2f) || // /
            (n  < 0x20)    // the control characters
          )
        {
          containedInvalidCharacters = true;
        }
      }

      return containedInvalidCharacters;
    }

  }

}

M
Mo Patel

The most accurate approach is going to be using some interop code from the shlwapi.dll

[DllImport(SHLWAPI, CharSet = CharSet.Unicode)]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
[ResourceExposure(ResourceScope.None)]
internal static extern bool PathIsDirectory([MarshalAsAttribute(UnmanagedType.LPWStr), In] string pszPath);

You would then call it like this:

#region IsDirectory
/// <summary>
/// Verifies that a path is a valid directory.
/// </summary>
/// <param name="path">The path to verify.</param>
/// <returns><see langword="true"/> if the path is a valid directory; 
/// otherwise, <see langword="false"/>.</returns>
/// <exception cref="T:System.ArgumentNullException">
/// <para><paramref name="path"/> is <see langword="null"/>.</para>
/// </exception>
/// <exception cref="T:System.ArgumentException">
/// <para><paramref name="path"/> is <see cref="F:System.String.Empty">String.Empty</see>.</para>
/// </exception>
public static bool IsDirectory(string path)
{
    return PathIsDirectory(path);
}

Ugly. I hate interop to do these simple tasks. And it's not portable. and it's ugly. Did I say that it's ugly? :)
@SoMoS It may be "ugly" in your opinion, but it is still the most accurate approach. Yes, it's not a portable solution but that wasn't what the question asked.
What do you mean exactly with accurate? It gives the same results as the answer from Quinn Wilson and required interop which breaks portability. To me its as accurate as the other solutions and have side effects others don't.
There's a Framework API to do this. Using Interop is not the way to go.
Yes this works, but it is NOT the "most accurate" solution--no more than using the existing .NET Framework. Instead, you take 6 lines of code to replace what can be done in one line with the .NET Framework, and lock yourself into using Windows only, as opposed to leaving open the ability to port this with the Mono Project. Never use Interop when the .NET Framework offers a more elegant solution.
I
IAbstract
public bool IsDirectory(string path) {
    return string.IsNullOrEmpty(Path.GetFileName(path)) || Directory.Exists(path);
}

Checks if the path file name is an empty string, or if the directory exists. This way you won't have the file attributes error while still providing redundancies for a possible exists failure.


l
lhan

I came across this when facing a similar problem, except I needed to check if a path is for a file or folder when that file or folder may not actually exist. There were a few comments on answers above that mentioned they would not work for this scenario. I found a solution (I use VB.NET, but you can convert if you need) that seems to work well for me:

Dim path As String = "myFakeFolder\ThisDoesNotExist\"
Dim bIsFolder As Boolean = (IO.Path.GetExtension(path) = "")
'returns True

Dim path As String = "myFakeFolder\ThisDoesNotExist\File.jpg"
Dim bIsFolder As Boolean = (IO.Path.GetExtension(path) = "")
'returns False

Hopefully this can be helpful to someone!


have you tried the Path.HasExtension method?
If it doesn't exist, then it's not a file or a directory. Any name can be created as either. If you intend to create it, then you should know what you're creating, and if you don't, then why could you possibly need this information?
A folder can be named test.txt and a file can be named test - in these cases your code would return incorrect results
There's a .Exists method in the System.IO.FIle and System.IO.Directory classes. that's the thing to do. Directories can have extensions; I see it frequently.
M
MaxOvrdrv

soooo late in the game i know, but thought i'd share this anyway. If you are solely working with the paths as strings, figuring this out is easy as pie:

private bool IsFolder(string ThePath)
{
    string BS = Path.DirectorySeparatorChar.ToString();
    return Path.GetDirectoryName(ThePath) == ThePath.TrimEnd(BS.ToCharArray());
}

for example: ThePath == "C:\SomeFolder\File1.txt" would end up being this:

return "C:\SomeFolder" == "C:\SomeFolder\File1.txt" (FALSE)

Another example: ThePath == "C:\SomeFolder\" would end up being this:

return "C:\SomeFolder" == "C:\SomeFolder" (TRUE)

And this would also work without the trailing backslash: ThePath == "C:\SomeFolder" would end up being this:

return "C:\SomeFolder" == "C:\SomeFolder" (TRUE)

Keep in mind here that this only works with the paths themselves, and not the relationship between the path and the "physical disk"... so it can't tell you if the path/file exists or anything like that, but it sure can tell you if the path is a folder or a file...


Does not work with System.IO.FileSystemWatcher since when a directory is deleted it sends c:\my_directory as an argument which is the same when a extension less file c:\my_directory is deleted.
GetDirectoryName('C:\SomeFolder') returns 'C:\', so your last case doesn't work. This doesn't distinguish between directories and files with no extensions.
You erroneously assume that a directory path will always include the final "\". For example, Path.GetDirectoryName("C:\SomeFolder\SomeSubFolder") will return C:\SomeFolder. Notice that your own examples of what GetDirectoryName returns show that it returns a path that does not end in a backslash. This means if someone uses GetDirectoryName elsewhere to get a directory path, and then feeds it to your method, they will get the wrong answer.
j
jamie

If you want to find directories, including those that are marked "hidden" and "system", try this (requires .NET V4):

FileAttributes fa = File.GetAttributes(path);
if(fa.HasFlag(FileAttributes.Directory)) 

J
Joe Stellato

I needed this, the posts helped, this gets it down to one line, and if the path isn't a path at all, it just returns and exits the method. It addresses all of the above concerns, doesn't need the trailing slash either.

if (!Directory.Exists(@"C:\folderName")) return;

d
dba

I see, I'm 10 years too late to the party. I was facing the situation, where from some property I can receive either a file name or a full file path. If there is no path provided, I have to check the file-existence by attaching a "global" directory-path provided by another property.

In my case

var isFileName = System.IO.Path.GetFileName (str) == str;

did the trick. Ok, it's not magic, but perhaps this could save someone a few minutes of figuring out. Since this is merely a string-parsing, so Dir-names with dots may give false positives...


S
Stu1983

I use the following, it also tests the extension which means it can be used for testing if the path supplied is a file but a file that doesn't exist.

private static bool isDirectory(string path)
{
    bool result = true;
    System.IO.FileInfo fileTest = new System.IO.FileInfo(path);
    if (fileTest.Exists == true)
    {
        result = false;
    }
    else
    {
        if (fileTest.Extension != "")
        {
            result = false;
        }
    }
    return result;
}

FileInfo Extension is (IMAO) a good option to check on non-existent paths
your second condition (else) is smelly. if it is not an existing file then you dont know what it could possibly be (directories can end with something like ".txt" too).
D
Diaa Eddin
using System;
using System.IO;
namespace FileOrDirectory
{
     class Program
     {
          public static string FileOrDirectory(string path)
          {
               if (File.Exists(path))
                    return "File";
               if (Directory.Exists(path))
                    return "Directory";
               return "Path Not Exists";
          }
          static void Main()
          {
               Console.WriteLine("Enter The Path:");
               string path = Console.ReadLine();
               Console.WriteLine(FileOrDirectory(path));
          }
     }
}

M
Michael Socha

Using the selected answer on this post, I looked at the comments and give credence to @ŞafakGür, @Anthony and @Quinn Wilson for their info bits that lead me to this improved answer which I wrote and tested:

    /// <summary>
    /// Returns true if the path is a dir, false if it's a file and null if it's neither or doesn't exist.
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    public static bool? IsDirFile(this string path)
    {
        bool? result = null;

        if(Directory.Exists(path) || File.Exists(path))
        {
            // get the file attributes for file or directory
            var fileAttr = File.GetAttributes(path);

            if (fileAttr.HasFlag(FileAttributes.Directory))
                result = true;
            else
                result = false;
        }

        return result;
    }

Seems a bit wasteful to check for the attributes after already checking for Directory/File Exists()? Those two calls alone do all the work needed here.
M
Minute V

Maybe for UWP C#

public static async Task<IStorageItem> AsIStorageItemAsync(this string iStorageItemPath)
    {
        if (string.IsNullOrEmpty(iStorageItemPath)) return null;
        IStorageItem storageItem = null;
        try
        {
            storageItem = await StorageFolder.GetFolderFromPathAsync(iStorageItemPath);
            if (storageItem != null) return storageItem;
        } catch { }
        try
        {
            storageItem = await StorageFile.GetFileFromPathAsync(iStorageItemPath);
            if (storageItem != null) return storageItem;
        } catch { }
        return storageItem;
    }

m
martinthebeardy

Very late to the party here but I've found the Nullable<Boolean> return value to be quite ugly - IsDirectory(string path) returning null doesn't equate to a non-existent path without verbose commenting, so I've come up with the following:

public static class PathHelper
{
    /// <summary>
    /// Determines whether the given path refers to an existing file or directory on disk.
    /// </summary>
    /// <param name="path">The path to test.</param>
    /// <param name="isDirectory">When this method returns, contains true if the path was found to be an existing directory, false in all other scenarios.</param>
    /// <returns>true if the path exists; otherwise, false.</returns>
    /// <exception cref="ArgumentNullException">If <paramref name="path"/> is null.</exception>
    /// <exception cref="ArgumentException">If <paramref name="path"/> equals <see cref="string.Empty"/></exception>
    public static bool PathExists(string path, out bool isDirectory)
    {
        if (path == null) throw new ArgumentNullException(nameof(path));
        if (path == string.Empty) throw new ArgumentException("Value cannot be empty.", nameof(path));

        isDirectory = Directory.Exists(path);

        return isDirectory || File.Exists(path);
    }
}

This helper method is written to be verbose and concise enough to understand the intent the first time you read it.

/// <summary>
/// Example usage of <see cref="PathExists(string, out bool)"/>
/// </summary>
public static void Usage()
{
    const string path = @"C:\dev";

    if (!PathHelper.PathExists(path, out var isDirectory))
        return;

    if (isDirectory)
    {
        // Do something with your directory
    }
    else
    {
        // Do something with your file
    }
}

T
TinyRacoon

Just adding a fringe case - "Folder Selection." in path

In my app I get recently opened paths passed to me, some of which have "Folder Selection." at the end.

Some FileOpenDialogs and WinMerge add "Folder Selection." to paths (it's true).

https://i.stack.imgur.com/VSZ4z.png

But under Windows OS "Folder Selection." is not an advised file or folder name (as in don't do it, ever - shakes fist). As said here: http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx

Do not end a file or directory name with a space or a period. Although the underlying file system may support such names, the Windows shell and user interface does not. However, it is acceptable to specify a period as the first character of a name. For example, ".temp".

So whilst "Folder Selection." shouldn't be used, it can be. (awesome).

Enough explanation - my code (I like enums a lot):

public static class Utility
{
    public enum ePathType
    {
        ePathType_Unknown = 0,
        ePathType_ExistingFile = 1,
        ePathType_ExistingFolder = 2,
        ePathType_ExistingFolder_FolderSelectionAdded = 3,
    }

    public static ePathType GetPathType(string path)
    {
        if (File.Exists(path) == true) { return ePathType.ePathType_ExistingFile; }
        if (Directory.Exists(path) == true) { return ePathType.ePathType_ExistingFolder; }

        if (path.EndsWith("Folder Selection.") == true)
        {
            // Test the path again without "Folder Selection."
            path = path.Replace("\\Folder Selection.", "");
            if (Directory.Exists(path) == true)
            {
                // Could return ePathType_ExistingFolder, but prefer to let the caller known their path has text to remove...
                return ePathType.ePathType_ExistingFolder_FolderSelectionAdded;
            }
        }

        return ePathType.ePathType_Unknown;
    }
}

佚名

Wouldn't this work?

var isFile = Regex.IsMatch(path, @"\w{1,}\.\w{1,}$");

This wouldn't work only because folder names can have periods in them
Also files don't have to have periods in them.