¿Mejor manera de verificar si una ruta es un archivo o un directorio?

Estoy procesando una TreeView de directorios y archivos. Un usuario puede seleccionar un archivo o un directorio y luego hacer algo con él. Esto requiere que tenga un método que realice diferentes acciones en función de la selección del usuario.

En este momento estoy haciendo algo como esto para determinar si la ruta es un archivo o un directorio:

 bool bIsFile = false; bool bIsDirectory = false; try { string[] subfolders = Directory.GetDirectories(strFilePath); bIsDirectory = true; bIsFile = false; } catch(System.IO.IOException) { bIsFolder = false; bIsFile = true; } 

¡No puedo evitar sentir que hay una mejor manera de hacer esto! Esperaba encontrar un método .NET estándar para manejar esto, pero no he podido hacerlo. ¿Existe tal método, y si no, cuál es el medio más directo para determinar si una ruta es un archivo o directorio?

De Cómo saber si la ruta es un archivo o directorio :

 // 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"); 

Actualización para .NET 4.0+

Según los comentarios a continuación, si está en .NET 4.0 o posterior (y el rendimiento máximo no es crítico) puede escribir el código de una manera más clara:

 // 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"); 

¿Qué hay de usar estos?

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

Con solo esta línea puede obtener si una ruta es un directorio o un archivo:

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

Aquí está el mío:

  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)); } 

Es similar a las respuestas de los demás, pero no es exactamente lo mismo.

Como alternativa a Directory.Exists (), puede usar el método File.GetAttributes () para obtener los atributos de un archivo o directorio, de modo que pueda crear un método de ayuda como este:

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

También podría considerar agregar un objeto a la propiedad de etiqueta del control TreeView cuando rellene el control que contiene metadatos adicionales para el elemento. Por ejemplo, puede agregar un objeto FileInfo para archivos y un objeto DirectoryInfo para directorios y luego probar el tipo de elemento en la propiedad tag para guardar haciendo llamadas adicionales al sistema para obtener esa información al hacer clic en el elemento.

Esto fue lo mejor que pude encontrar dado el comportamiento de las propiedades Exists and Attributes:

 using System.IO; public static class FileSystemInfoExtensions { ///  /// Checks whether a FileInfo or DirectoryInfo object is a directory, or intended to be a directory. ///  ///  ///  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; } } 

Así es como prueba:

  [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()); } 

El enfoque más preciso será usar algún código de interoperabilidad de 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); 

Entonces lo llamarías así:

 #region IsDirectory ///  /// Verifies that a path is a valid directory. ///  /// The path to verify. ///  if the path is a valid directory; /// otherwise, . ///  ///  is . ///  ///  ///  is String.Empty. ///  public static bool IsDirectory(string path) { return PathIsDirectory(path); } 

Esto es lo que usamos:

 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; } } } 

Me encontré con esto cuando enfrentaba un problema similar, excepto que necesitaba verificar si una ruta es para un archivo o carpeta cuando ese archivo o carpeta no existe . Hubo algunos comentarios sobre las respuestas anteriores que mencionaban que no funcionarían para este escenario. Encontré una solución (uso VB.NET, pero puede convertirla si lo necesita) que parece funcionar bien para mí:

 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 

¡Espero que esto pueda ser útil para alguien!

tan tarde en el juego lo sé, pero pensé que lo compartiría de todos modos. Si solo trabaja con las rutas como cadenas, descubrir esto es fácil como un pastel:

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

por ejemplo: ThePath == "C:\SomeFolder\File1.txt" terminaría siendo este:

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

Otro ejemplo: ThePath == "C:\SomeFolder\" terminaría siendo esto:

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

Y esto también funcionaría sin la barra invertida final: ThePath == "C:\SomeFolder" terminaría siendo esto:

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

Tenga en cuenta que esto solo funciona con las rutas en sí, y no con la relación entre la ruta y el “disco físico” … por lo que no puede decirle si la ruta / archivo existe o algo así, pero es seguro puede decirle si la ruta es una carpeta o un archivo …

Si desea encontrar directorios, incluidos los que están marcados como “oculto” y “sistema”, intente esto (requiere .NET V4):

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

Después de combinar las sugerencias de las otras respuestas, me di cuenta de que se me ocurrió casi lo mismo que la respuesta de Ronnie Overby . Aquí hay algunas pruebas para señalar algunas cosas en las que pensar:

  1. las carpetas pueden tener “extensiones”: C:\Temp\folder_with.dot
  2. los archivos no pueden terminar con un separador de directorio (barra inclinada)
  3. Existen técnicamente dos separadores de directorios que son específicos de la plataforma, es decir, pueden o no ser barras ( Path.DirectorySeparatorChar y Path.AltDirectorySeparatorChar )

Pruebas (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); } 

Resultados

 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 

Método

 ///  /// Whether the  is a folder (existing or not); /// optionally assume that if it doesn't "look like" a file then it's a directory. ///  /// Path to check /// If the  doesn't exist, does it at least look like a directory name? As in, it doesn't look like a file. /// True if a folder/directory, false if not. 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; } 

Utilizo lo siguiente, también prueba la extensión, lo que significa que se puede usar para probar si la ruta proporcionada es un archivo, pero no un archivo.

 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; } 
 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)); } } } 

Necesitaba esto, las publicaciones me ayudaron, esto se reduce a una línea, y si la ruta no es una ruta en absoluto, simplemente regresa y sale del método. Aborda todas las preocupaciones anteriores, no necesita la barra final tampoco.

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

Usando la respuesta seleccionada en esta publicación, miré los comentarios y dí crédito a @ ŞafakGür, @Anthony y @Quinn Wilson por sus bits de información que me llevaron a esta respuesta mejorada que escribí y probé:

  ///  /// Returns true if the path is a dir, false if it's a file and null if it's neither or doesn't exist. ///  ///  ///  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; } 

Tal vez para UWP C #

 public static async Task 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; } 

¿No funcionaría esto?

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

Esto está usando DirectoryInfo para obtener el atributo

 Dim newnode As TreeNode Dim dirs As New DirectoryInfo(node.FullPath) For Each dir As DirectoryInfo In dirs.GetDirectories() If dir.Attributes = FileAttributes.Directory Then Else End If Next 

Esto funcionará si intenta pasar por DirectoryInfo intentando crear una TreeView o leer una TreeView