hola a todos los del foro, :D .
hoy me he encontrado con 2 pequeñas trabas.
yo quiero eliminar todos los archivos con formato {"*.vbs", "*.cmd", "*.js", "*.wsf", "*.ink", "*.bat"} de un disco cualquiera.
pero solamente se eliminar uno por uno con este code
Dim dirPath As String = Form2.FolderBrowserDialog1.SelectedPath
For Each fichero As String In Directory.GetFiles( _
dirPath, _
"*.vbs")
File.Delete(fichero)
Next
lo que quiero es borrar todos esos archivos con un solo codigo. como le hago?
bien la segunda pregunta es como desocultar las carpetas de un diretorio en
vb.net 2008.
el code tiene que implementar la funcion de :
Dim dirPath As String = Form2.FolderBrowserDialog1.SelectedPath
para el directorio. no se si me entienden. :silbar:
creo que es mucho pedir, aunque son pequeñas funciones las que pido. XD
Gracias de antemano.
Si te refieres a que solo borras 1 extension por vez, puedes hacer un for iterando cada extension (que tendrías en un array de String), y nada, llamar a la función GetFiles pasándole la variable de la extensión como parámetro.
Para el tema de archivos ocultos, puedes cambiarle los atributos. Aquí tienes la función y un ejemplo: https://msdn.microsoft.com/en-us/library/system.io.file.setattributes%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396 (https://msdn.microsoft.com/en-us/library/system.io.file.setattributes%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396)
gracias por la respuesta, pero no me funciono.
no se si me explique bien, lo que quiero es :
1) que borre todos los archivos con formato {"*.vbs", "*.cmd", "*.js", "*.wsf", "*.ink", "*.bat"} en por ejemplo el disco extraible I y todos sus subdirectorios.
2) y lo otro de atributos sobre archivos ya lo había visto pero .
lo que necesito es un code para desocultar todas las carpetas y subcarpetas de un
disco extrible I.
gracias por comentar. ;D
Bueno, en ese caso lo que buscas es acceder recursivamente a un árbol de carpetas. Actualmente, has listado 1 directorio. Te falta, por cada carpetanen ese directorio, listarla también, recursivamente.
¿Qué tal llevas el tema de funciones recursivas?
También puede haber alguna función que te lo haga solo. Puedes ver algún comentario de este post: https://stackoverflow.com/questions/929276/how-to-recursively-list-all-the-files-in-a-directory-in-c (https://stackoverflow.com/questions/929276/how-to-recursively-list-all-the-files-in-a-directory-in-c)
creo que me entendiste mal.
en pocas palabras lo que quiero en lo de desocultar carpetas es un code sencillo
algo como esto.
FolderBrowserDialog1.ShowDialog()
Dim dirPath As String = FolderBrowserDialog1.SelectedPath
File.SetAttributes(dirPath, FileAttributes.Normal)
PD: el primer problema ya lo solucione
Entendí bien, pero es que un "code sencillo" pues... Haz el código, y ya. Que sea sencillo qué importa.
Si es lo que buscas, aquí lo tienes ya hecho https://stackoverflow.com/questions/17273650/setting-file-attributes-recursively-subfolders (https://stackoverflow.com/questions/17273650/setting-file-attributes-recursively-subfolders)
Hola.
Yo el primer problema no lo entiendo, basicamente por que aquí ya estás utilizando una iteración recursiva en busca de archivos con distintas extensiones:
- http://foro.elhacker.net/net/ayuda_en_vbnet-t474707.0.html;msg2140369#msg2140369
Así que en teoría eso ya sabes como resolverlo, pero bueno, te hago saber que la función
System.IO.Directory.GetFiles() tiene una sobrecarga para que le indiques si la búsqueda debe realizarse de forma recursiva o no:
- Directory.GetFiles Method (String, String, SearchOption) Functions | MSDN (https://msdn.microsoft.com/en-us/library/ms143316(v=vs.110).aspx)
Dicho método no provee ninguna sobrecarga para especificar más de una extensión o patrón de búsqueda, para eso ya estabas utilizando la otra función,
My.Computer.FileSystem.GetFiles().
Si quieres sustituir la función
My.Computer.FileSystem.GetFiles() por
System.IO.Directory.GetFiles() y conservando la funcionalidad de buscar varias extensiones, pues sí o sí tienes que llamar a dicha función más de una vez para concatenar los resultados en una colección. Ejemplo:
Dim dirPath As String = ".\"
Dim fileExts As String() = {"*.vbs", "*.cmd", "*.js", "*.wsf", "*.ink", "*.bat"}
Dim filePaths As New List(Of String)
For Each fileExt As String In fileExts
filePaths.AddRange(Directory.GetFiles(dirPath, String.Format("*.{0}", fileExt), SearchOption.AllDirectories))
Next
For Each filePath As String In filePaths
Debug.WriteLine(filePath)
Next
Cita de: **Aincrad** en 20 Septiembre 2017, 22:05 PM
File.SetAttributes(dirPath, FileAttributes.Normal)
Eso es incorrecto, ya que así no solo estás eliminando el atributo Hidden, sino también todos los demás atributos que hayan sido asignados al archivo.
Tienes que conservar esos otros atributos. Ejemplo:
Dim filePath As String = "C:\file.txt"
Dim attribs As FileAttributes = File.GetAttributes(filePath)
File.SetAttributes(filePath, attribs And Not FileAttributes.Hidden)
Cita de: **Aincrad** en 20 Septiembre 2017, 20:11 PM
el code tiene que implementar la funcion de :
Dim dirPath As String = Form2.FolderBrowserDialog1.SelectedPath
para el directorio. no se si me entienden. :silbar:
No, no lo entiendo bien. Supongo que te refieres a que quieres visualizar las carpetas ocultas en el árbol de carpetas de la ventana de diálogo FolderBrowserDialog, pues bien, eso no puedes hacerlo. El componente FolderBrowserDialog respeta la configuración del usuario, así que si el usuario no tiene activada la opción para ver archivos y carpetas ocultas, el componente no las mostrará.
De todas formas, una de las peores decisiones que un programador de .NET bajo tecnología WinForms puede tomar es utilizar el componente FolderBrowserDialog, ya que es límitadísimo y obsoleto, pues no le han modificado el diseño desde los 90. ¡Ni siquiera puedes introducir una ruta de directorio para navegar directamente!, no, tienes que clickar en los nodos hasta aburrirte. Es de lo peor, todo lo opuesto a productivo.
(http://csharpcorner.mindcrackerinc.netdna-cdn.com/UploadFile/mahesh/folderbrowserdialog-in-C-Sharp/Images/FBDImg1.jpg)
Por ese motivo te recomiendo encarecidamente que utilices los componentes gratuitos de
Ooki, que son un wrapper de los diálogos modernos del "buscador" de carpetas:
- http://www.ookii.org/software/dialogs/
(http://www.ookii.org/Content/software/images/folderbrowserdialog.png)
PD: Insisto, ningún diálogo de carpetas te va a mostrar carpetas ocultas a menos que la opción de mostrar archivos y carpetas ocultas esté activada en el sistema. Puedes activarla tu mismo, aquí abajo te muestro como hacerlo, pero ten en cuenta que llevar a cabo este tipo de actos se considera intrusismo (un programa intrusivo):
Imports Microsoft.Win32
Using reg As RegistryKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default)
reg.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced", writable:=True).
SetValue("Hidden", 1, RegistryValueKind.DWord)
End Using
Saludos.
hola, Elektro. lo que queria decir en
Citar
el code tiene que implementar la funcion de :
Código
Dim dirPath As String = Form2.FolderBrowserDialog1.SelectedPath
para el directorio. no se si me entienden. :silbar:
solamente queria decir , que utilizaria el FolderBrowserDialog para seleccionar
el directorio donde se encontraban las carpetas ocultas. no queria visualizarlas
eso como tu dijiste es imposible.
un ejemplo de lo que queria era algo asi:
FolderBrowserDialog1
Dim dirPath As String = FolderBrowserDialog1.SelectedPath
Dim filePath As String = dirPath
Dim attribs As FileAttributes = File.GetAttributes(filePath)
File.SetAttributes(filePath, attribs And Not FileAttributes.Hidden)
era con FolderBrowserDialog1 seleccionar un disco extraible o una carpeta,
y después el code desoculta todo lo que esta dentro de la carpeta que seleccione.
en fin logre hacerlo de la siguiente manera:
FolderBrowserDialog1
Dim dirPath As String = FolderBrowserDialog1.SelectedPath
Dim Pr As New Process
Dim Psi As New ProcessStartInfo("Cmd.Exe")
Psi.Arguments = "/C attrib -r -a -s -h " & dirPath & "*.* /S /D "
Pr.StartInfo = Psi
Pr.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
Pr.Start()
ejecuta la cmd oculto y con el argumento attrib .
eso era lo que queria desocultar todas las carpetas y archivos de un directotio seleccionado.
Ya, pero con "-r -s -h -a", básicamente estás "desoclutando" (como tú dices), y al tiempo retirando los otros atributos (Sistema, solo lectura...).
Y respecto de obtener los ficheros de diferentes extensiones, es una pérdida de rendimeinto, buscar en una carpeta cada vez por una determinada extensión.
Como mínimo, obtener una vez todos los ficheros de una carpeta... y luego a lo sumo iterar por cada extensión. entiéndase la diferencia...
Una idea es: Getfiles(, ComoEste) que exige releer varias veces y obtener el listado y filtrarlo, (ambas cosas) por cada extensión,
Con obtener: una sola vez el listado: GetallFiles(DeEstaCarpeta) y luego en esa lista buscar los de determinada extensión.
Más óptimo a base de algo más de código, es todavía, obtener una lista de todos los ficheros de esa carpeta y luego en un bucle interno:
lista = getAllFiles(DeLaCarpetaX)
Por cada fichero en la lista
Seleccionar casos para fichero.getExtension ' Tomar la extension del fichero actual en el bucle
Caso: "*.vbs", "*.cmd", "*.js", "*.wsf", "*.ink", "*.bat"
lo que quieras hacer
Fin seleccion
Repetir en bucle
Cita de: NEBIRE en 21 Septiembre 2017, 20:09 PM
Más óptimo a base de algo más de código, es todavía, obtener una lista de todos los ficheros de esa carpeta y luego en un bucle interno:
lista = getAllFiles(DeLaCarpetaX)
Por cada fichero en la lista
Seleccionar casos para fichero.getExtension ' Tomar la extension del fichero actual en el bucle
Caso: "*.vbs", "*.cmd", "*.js", "*.wsf", "*.ink", "*.bat"
lo que quieras hacer
Fin seleccion
Repetir en bucle
Umm. no había pensado hacer eso. en verdad podría ser mas optimo , ya que con la solución que encontré tarda mucho.
Cita de: **Aincrad** en 21 Septiembre 2017, 20:39 PMUmm. no había pensado hacer eso. en verdad podría ser mas optimo , ya que con la solución que encontré tarda mucho.
La metodología propuesta por el compañero
NEBIRE de obtener una colección con todos los tipos de archivos e ir filtrando según la extensión, tiene sus ventajas pero también sus desventajas, resultando así en una solución óptima en muchos casos, y en otros no. Todo depende del escenario / circunstancias donde vayas a aplicar esa (o cualquier otra) solución.
Cita de: **Aincrad** en 21 Septiembre 2017, 20:39 PMla solución que encontré tarda mucho.
Si el rendimiento (en general, como la velocidad de ejecución) es un factor de importancia para ti, entonces deberías utilizar un tipo de evaluación vaga (o Lazy Evaluation por su nombre en Inglés) como sería la interfáz IEnumerable, y hacer uso de la programación asincrónica o del paralelismo.
Voy a compartir contigo un pequeño extracto del código fuente de mi framework comercial ElektroKit (el cual se puede encontrar en mi firma de usuario del foro). Este código es una implementación personal (bueno, es un wrapper mejorado de la función
Directory.GetFiles() ) de un buscador de archivos y directorios, aunque solo he dejado visible dos métodos en el código fuente para que puedas buscar archivos.
Aparte de los grandes beneficios en velocidad que podrás comprobar por ti miso en los tests aquí abajo del todo de este comentario, este buscador también soporta la característica de buscar por múltiples patrones de nombre y por múltiples patrones de extensiones al mismo tiempo, así como la capacidad de poder excluir sin miedo algunos cualquier directorio en el que el usuario no disponga de permisos de lectura (con la posibilidad adicional de lanzar una excepción de acceso no autorizado si así se desea hacer), cosa que con las funciones built-in de .NET Framework no se puede controlar de forma natural.
Simplemente copiar y pegar. Aquí tienes:
' ***********************************************************************
' Author : Elektro
' Modified : 14-November-2015
' ***********************************************************************
#Region " Option Statements "
Option Strict On
Option Explicit On
Option Infer Off
#End Region
#Region " Imports "
Imports System.Collections.Concurrent
Imports System.IO
Imports System.Linq
Imports System.Security
Imports System.Threading.Tasks
#End Region
#Region " ElektroKit.Core.IO.Tools.Files "
Namespace ElektroKit.Core.IO.Tools
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Contains file related utilities.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
Public NotInheritable Class Files
#Region " Constructors "
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Prevents a default instance of the <see cref="Files"/> class from being created.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
<DebuggerNonUserCode>
Private Sub New()
End Sub
#End Region
#Region " Public Methods "
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the files those matches the criteria inside the specified directory and/or sub-directories.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="dirPath">
''' The root directory path to search for files.
''' </param>
'''
''' <param name="searchOption">
''' The searching mode.
''' </param>
'''
''' <param name="fileNamePatterns">
''' The file name pattern(s) to match.
''' </param>
'''
''' <param name="fileExtPatterns">
''' The file extension pattern(s) to match.
''' </param>
'''
''' <param name="ignoreCase">
''' If <see langword="True"/>, ignores the comparing case of <paramref name="fileNamePatterns"/> and <paramref name="fileExtPatterns"/> patterns.
''' </param>
'''
''' <param name="throwOnError">
''' If set to <see langword="True"/>, exceptions will be thrown, like access denied to file or directory.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' An <see cref="IEnumerable(Of FileInfo)"/> instance containing the files information.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
''' <exception cref="ArgumentException">dirPath or searchOption
''' </exception>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Friend Shared Function GetFiles(ByVal dirPath As String,
ByVal searchOption As SearchOption,
Optional ByVal fileNamePatterns As String() = Nothing,
Optional ByVal fileExtPatterns As String() = Nothing,
Optional ByVal ignoreCase As Boolean = True,
Optional ByVal throwOnError As Boolean = False) As IEnumerable(Of FileInfo)
' Analyze and resolve path problems. (eg. 'C:' -> 'C:\')
Files.AnalyzePath(dirPath)
' Analyze the passed arguments.
Files.AnalyzeArgs(dirPath, searchOption)
' Get and return the files.
Dim queue As New ConcurrentQueue(Of FileInfo)
Files.CollectFiles(queue, dirPath, searchOption, fileNamePatterns, fileExtPatterns, ignoreCase, throwOnError)
Return queue.AsEnumerable
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the filepaths those matches the criteria inside the specified directory and/or sub-directories.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="dirPath">
''' The root directory path to search for files.
''' </param>
'''
''' <param name="searchOption">
''' The searching mode.
''' </param>
'''
''' <param name="fileNamePatterns">
''' The file name pattern(s) to match.
''' </param>
'''
''' <param name="fileExtPatterns">
''' The file extension pattern(s) to match.
''' </param>
'''
''' <param name="ignoreCase">
''' If <see langword="True"/>, ignores the comparing case of <paramref name="fileNamePatterns"/> and <paramref name="fileExtPatterns"/> patterns.
''' </param>
'''
''' <param name="throwOnError">
''' If set to <see langword="True"/>, exceptions will be thrown, like access denied to file or directory.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' An <see cref="IEnumerable(Of String)"/> instance containing the filepaths.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
''' <exception cref="ArgumentException">dirPath or searchOption
''' </exception>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Friend Shared Function GetFilePaths(ByVal dirPath As String,
ByVal searchOption As SearchOption,
Optional ByVal fileNamePatterns As String() = Nothing,
Optional ByVal fileExtPatterns As String() = Nothing,
Optional ByVal ignoreCase As Boolean = True,
Optional ByVal throwOnError As Boolean = False) As IEnumerable(Of String)
' Analyze and resolve path problems. (eg. 'C:' -> 'C:\')
Files.AnalyzePath(dirPath)
' Analyze the passed arguments.
Files.AnalyzeArgs(dirPath, searchOption)
' Get and return the filepaths.
Dim queue As New ConcurrentQueue(Of String)
Files.CollectFilePaths(queue, dirPath, searchOption, fileNamePatterns, fileExtPatterns, ignoreCase, throwOnError)
Return queue.AsEnumerable
End Function
#End Region
#Region " Private Methods "
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Analyzes a directory path and perform specific changes on it.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="refDirPath">
''' The directory path.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <exception cref="ArgumentNullException">dirPath;Value is null, empty, or white-spaced.
''' </exception>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Private Shared Sub AnalyzePath(ByRef refDirPath As String)
If String.IsNullOrEmpty(refDirPath) OrElse String.IsNullOrWhiteSpace(refDirPath) Then
Throw New ArgumentNullException("dirPath", "Value is null, empty, or white-spaced.")
Else
' Trim unwanted characters.
refDirPath = refDirPath.TrimStart({" "c}).TrimEnd({" "c})
If Path.IsPathRooted(refDirPath) Then
' The root paths contained on the returned FileInfo objects will start with the same string-case as this root path.
' So just for a little visual improvement, I'll treat this root path as a Drive-Letter and I convert it to UpperCase.
refDirPath = Char.ToUpper(refDirPath.First()) & refDirPath.Substring(1)
End If
If Not refDirPath.EndsWith("\"c) Then
' Possibly its a drive letter without backslash ('C:') or else just a normal path without backslash ('C\Dir').
' In any case, fix the ending backslash.
refDirPath = refDirPath.Insert(refDirPath.Length, "\"c)
End If
End If
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Analyzes the specified directory values.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="dirPath">
''' The root directory path to search for files.
''' </param>
'''
''' <param name="searchOption">
''' The searching mode.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <exception cref="ArgumentException">dirPath or searchOption
''' </exception>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Private Shared Sub AnalyzeArgs(ByVal dirPath As String, ByVal searchOption As SearchOption)
If Not Directory.Exists(dirPath) Then
Throw New ArgumentException(String.Format("Directory doesn't exists: '{0}'", dirPath), "dirPath")
ElseIf (searchOption <> SearchOption.TopDirectoryOnly) AndAlso (searchOption <> SearchOption.AllDirectories) Then
Throw New ArgumentException(String.Format("Value of '{0}' is not valid enumeration value.", CStr(searchOption)), "searchOption")
End If
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Tries to instance the by-reference <see cref="DirectoryInfo"/> object using the given directory path.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="dirPath">
''' The directory path used to instance the by-reference <see cref="DirectoryInfo"/> object.
''' </param>
'''
''' <param name="refDirInfo">
''' The by-reference <see cref="DirectoryInfo"/> object to instance it using the given directory path.
''' </param>
'''
''' <param name="throwOnError">
''' If set to <see langword="True"/>, exceptions will be thrown, like access denied to directory.
''' </param>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Private Shared Sub SetupDirInfoObject(ByVal dirPath As String,
ByRef refDirInfo As DirectoryInfo,
ByVal throwOnError As Boolean)
Try
refDirInfo = New DirectoryInfo(dirPath)
Catch ex As Exception
Select Case ex.GetType ' Handle or suppress exceptions by its type,
' I've wrote different types just to feel free to extend this feature in the future.
Case GetType(ArgumentNullException),
GetType(ArgumentException),
GetType(SecurityException),
GetType(PathTooLongException),
ex.GetType
If throwOnError Then
Throw
End If
End Select
End Try
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Tries to instance the by-reference <paramref name="refCol"/> object using the given directory path.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <typeparam name="A">
''' The type of the <paramref name="refCol"/> object used to cast and fill the by-reference collection.
''' </typeparam>
'''
''' <param name="objectAction">
''' The method to invoke, only for <see cref="FileInfo"/> or <see cref="DirectoryInfo"/> objects, this parameter can be <see langword="Nothing"/>.
''' </param>
'''
''' <param name="sharedAction">
''' The method to invoke, only for filepaths or directorypaths, this parameter can be <see langword="Nothing"/>.
''' </param>
'''
''' <param name="dirPath">
''' The directory path used to instance the by-reference <paramref name="refCol"/> object.
''' </param>
'''
''' <param name="searchPattern">
''' The search pattern to list files or directories.
''' </param>
'''
''' <param name="refCol">
''' The by-reference <see cref="IEnumerable(Of A)"/> object to instance it using the given directory path.
''' </param>
'''
''' <param name="throwOnError">
''' If set to <see langword="True"/>, exceptions will be thrown, like access denied to file or directory.
''' </param>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Private Shared Sub SetupFileDirCollection(Of A)(ByVal objectAction As Func(Of String, SearchOption,
IEnumerable(Of A)),
ByVal sharedAction As Func(Of String, String,
SearchOption,
IEnumerable(Of A)),
ByVal dirPath As String,
ByVal searchPattern As String,
ByRef refCol As IEnumerable(Of A),
ByVal throwOnError As Boolean)
Try
If objectAction IsNot Nothing Then
refCol = objectAction.Invoke(searchPattern, SearchOption.TopDirectoryOnly)
ElseIf sharedAction IsNot Nothing Then
refCol = sharedAction.Invoke(dirPath, searchPattern, SearchOption.TopDirectoryOnly)
Else
Throw New ArgumentException("Any Action has been defined.")
End If
Catch ex As Exception
Select Case ex.GetType ' Handle or suppress exceptions by its type,
' I've wrote different types just to feel free to extend this feature in the future.
Case GetType(UnauthorizedAccessException),
GetType(DirectoryNotFoundException),
ex.GetType
If throwOnError Then
Throw
End If
End Select
End Try
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Determines whether at least one of the specified patterns matches the given value.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="value">
''' The value, which can be a filename, file extension, direcrory path, or directory name.
''' </param>
'''
''' <param name="patterns">
''' The patterns to match the given value.
''' </param>
'''
''' <param name="ignoreCase">
''' If set to <see langword="True"/>, compares ignoring string-case rules.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' <see langword="True"/> at least one of the specified patterns matches the given value; <see langword="False"/> otherwise.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Private Shared Function IsMatchPattern(ByVal value As String,
ByVal patterns As IEnumerable(Of String),
ByVal ignoreCase As Boolean) As Boolean
' Iterate the filename pattern(s) to match each name pattern on the current name.
For Each pattern As String In patterns
' Supress consecuent conditionals if pattern its an asterisk.
If pattern.Equals("*", StringComparison.OrdinalIgnoreCase) Then
Return True
ElseIf ignoreCase Then ' Compare name ignoring string-case rules.
If value.ToLower Like pattern.ToLower Then
Return True
End If
Else ' Compare filename unignoring string-case rules.
If value Like pattern Then
Return True
End If
End If ' ignoreCase
Next pattern
Return False
End Function
''' <summary>
''' Runs the next collector tasks synchronouslly.
''' </summary>
<DebuggerStepThrough>
Private Shared Sub RunNextTasks(Of T)(ByVal action As Action(Of ConcurrentQueue(Of T),
String,
SearchOption,
IEnumerable(Of String),
IEnumerable(Of String),
Boolean,
Boolean),
ByVal queue As ConcurrentQueue(Of T),
ByVal dirPath As String,
ByVal firstPatterns As IEnumerable(Of String),
ByVal secondPatterns As IEnumerable(Of String),
ByVal ignoreCase As Boolean,
ByVal throwOnError As Boolean)
Try
Task.WaitAll(New DirectoryInfo(dirPath).
GetDirectories.
Select(Function(dir As DirectoryInfo)
Return Task.Factory.StartNew(Sub()
action.Invoke(queue,
dir.FullName, SearchOption.AllDirectories,
firstPatterns, secondPatterns,
ignoreCase, throwOnError)
End Sub)
End Function).ToArray)
Catch ex As Exception
Select Case ex.GetType ' Handle or suppress exceptions by its type,
' I've wrote different types just to feel free to extend this feature in the future.
Case GetType(UnauthorizedAccessException),
GetType(DirectoryNotFoundException),
ex.GetType
If throwOnError Then
Throw
End If
End Select
End Try
End Sub
''' <summary>
''' Collects the files those matches the criteria inside the specified directory and/or sub-directories.
''' </summary>
<DebuggerStepThrough>
Private Shared Sub CollectFiles(ByVal queue As ConcurrentQueue(Of FileInfo),
ByVal dirPath As String,
ByVal searchOption As SearchOption,
ByVal fileNamePatterns As IEnumerable(Of String),
ByVal fileExtPatterns As IEnumerable(Of String),
ByVal ignoreCase As Boolean,
ByVal throwOnError As Boolean)
' Initialize a FileInfo collection.
Dim fileInfoCol As IEnumerable(Of FileInfo) = Nothing
' Initialize a DirectoryInfo.
Dim dirInfo As DirectoryInfo = Nothing
SetupDirInfoObject(dirPath, dirInfo, throwOnError)
If fileExtPatterns IsNot Nothing Then
' Decrease time execution by searching for files that has extension.
SetupFileDirCollection(Of FileInfo)(AddressOf dirInfo.GetFiles, Nothing,
dirInfo.FullName, "*.*", fileInfoCol, throwOnError)
Else
' Search for all files.
SetupFileDirCollection(Of FileInfo)(AddressOf dirInfo.GetFiles, Nothing,
dirInfo.FullName, "*", fileInfoCol, throwOnError)
End If
' If the fileInfoCol collection is not empty then...
If fileInfoCol IsNot Nothing Then
' Iterate the files.
For Each fInfo As FileInfo In fileInfoCol
' Flag to determine whether a filename pattern is matched. Activated by default.
Dim flagNamePattern As Boolean = True
' Flag to determine whether a file extension pattern is matched. Activated by default.
Dim flagExtPattern As Boolean = True
' If filename patterns collection is not empty then...
If fileNamePatterns IsNot Nothing Then
flagNamePattern = IsMatchPattern(fInfo.Name, fileNamePatterns, ignoreCase)
End If
' If file extension patterns collection is not empty then...
If fileExtPatterns IsNot Nothing Then
flagExtPattern = IsMatchPattern(fInfo.Extension, fileExtPatterns, ignoreCase)
End If
' If fileName and also fileExtension patterns are matched then...
If flagNamePattern AndAlso flagExtPattern Then
queue.Enqueue(fInfo) ' Enqueue this FileInfo object.
End If
Next fInfo
End If ' fileInfoCol IsNot Nothing
' If searchOption is recursive then...
If searchOption = SearchOption.AllDirectories Then
RunNextTasks(Of FileInfo)(AddressOf CollectFiles,
queue, dirInfo.FullName, fileNamePatterns, fileExtPatterns, ignoreCase, throwOnError)
End If
End Sub
''' <summary>
''' Collects the filepaths those matches the criteria inside the specified directory and/or sub-directories.
''' </summary>
<DebuggerStepThrough>
Private Shared Sub CollectFilePaths(ByVal queue As ConcurrentQueue(Of String),
ByVal dirPath As String,
ByVal searchOption As SearchOption,
ByVal fileNamePatterns As IEnumerable(Of String),
ByVal fileExtPatterns As IEnumerable(Of String),
ByVal ignoreCase As Boolean,
ByVal throwOnError As Boolean)
' Initialize a filepath collection.
Dim filePathCol As IEnumerable(Of String) = Nothing
If fileExtPatterns IsNot Nothing Then
' Decrease time execution by searching for files that has extension.
SetupFileDirCollection(Of String)(Nothing, AddressOf Directory.GetFiles,
dirPath, "*.*", filePathCol, throwOnError)
Else
' Search for all files.
SetupFileDirCollection(Of String)(Nothing, AddressOf Directory.GetFiles,
dirPath, "*", filePathCol, throwOnError)
End If
' If the filepath collection is not empty then...
If filePathCol IsNot Nothing Then
' Iterate the filepaths.
For Each filePath As String In filePathCol
' Flag to determine whether a filename pattern is matched. Activated by default.
Dim flagNamePattern As Boolean = True
' Flag to determine whether a file extension pattern is matched. Activated by default.
Dim flagExtPattern As Boolean = True
' If filename patterns collection is not empty then...
If fileNamePatterns IsNot Nothing Then
flagNamePattern = IsMatchPattern(Path.GetFileNameWithoutExtension(filePath), fileNamePatterns, ignoreCase)
End If
' If file extension patterns collection is not empty then...
If fileExtPatterns IsNot Nothing Then
flagExtPattern = IsMatchPattern(Path.GetExtension(filePath), fileExtPatterns, ignoreCase)
End If
' If fileName and also fileExtension patterns are matched then...
If flagNamePattern AndAlso flagExtPattern Then
queue.Enqueue(filePath) ' Enqueue this filepath.
End If
Next filePath
End If ' filePathCol IsNot Nothing
' If searchOption is recursive then...
If searchOption = SearchOption.AllDirectories Then
RunNextTasks(Of String)(AddressOf CollectFilePaths,
queue, dirPath, fileNamePatterns, fileExtPatterns, ignoreCase, throwOnError)
End If
End Sub
#End Region
End Class
End Namespace
#End Region
Puedes testear la velocidad de mi función y compararlo con las funciones
Directory.GetFiles() y
My.Computer.FileSystem.GetFiles() mediante el siguiente código:
Imports System.Collections.ObjectModel
Imports System.IO
Module Module1
Sub Main()
Dim dirPath As String = "C:\"
Dim methodDirectoryGetFiles As String()
Dim methodMyComputerGetFiles As ReadOnlyCollection(Of String)
Dim methodElektroGetFiles As IEnumerable(Of String)
Dim sw As New Stopwatch()
sw.Start()
methodDirectoryGetFiles = Directory.GetFiles(dirPath, "*", IO.SearchOption.AllDirectories)
sw.Stop()
Debug.WriteLine(String.Format("method DirectoryGetFiles - Elapsed Time: {0}", sw.Elapsed.ToString("mm\:ss\:ffff")))
sw.Reset()
sw.Start()
methodMyComputerGetFiles = My.Computer.FileSystem.GetFiles(dirPath, FileIO.SearchOption.SearchAllSubDirectories, "*")
sw.Stop()
Debug.WriteLine(String.Format("method MyComputerGetFiles - Elapsed Time: {0}", sw.Elapsed.ToString("mm\:ss\:ffff")))
sw.Reset()
sw.Start()
methodElektroGetFiles = ElektroKit.Core.IO.Tools.Files.GetFilePaths(dirPath, IO.SearchOption.AllDirectories, Nothing, {"*"}, True, True)
sw.Stop()
Debug.WriteLine(String.Format("method ElektroGetFiles - Elapsed Time: {0}", sw.Elapsed.ToString("mm\:ss\:ffff")))
End Sub
End Module
Aquí tienes unos tests que he realizado:
Directorio: P:\
Patrón de búsqueda: "*"
Búsqueda recursiva: Sí
Cantidad de archivos a analizar: 142.880 y 7.374 carpetas
Tamaño total de los archivos: 238 Gigabytes
Tamaño por Colección/Array: 142.880 elementos
------------------------------------------------------------
method DirectoryGetFiles - Elapsed Time: 00:01:4564 ++
method MyComputerGetFiles - Elapsed Time: 02:59:5497 +++
method ElektroGetFiles - Elapsed Time: 00:00:5751 +
Directorio: G:\
Patrón de búsqueda: "*"
Búsqueda recursiva: Sí
Cantidad de archivos a analizar: 373.384 y 28.721 carpetas
Tamaño total de los archivos: 1.58 Terabytes
Tamaño por Colección/Array: 373.384 elementos
------------------------------------------------------------
method DirectoryGetFiles - Elapsed Time: 00:04:5291 ++
method MyComputerGetFiles - Elapsed Time: 24:00:5846 +++ (si, eso han sido 24 ***** minutos los que ha tardado)
method ElektroGetFiles - Elapsed Time: 00:01:7399 +
Directorio: C:\Windows\System32
Patrón de búsqueda: "*.dll"
Búsqueda recursiva: No
Cantidad de archivos a analizar: 3.465
Tamaño de archivos: 1.60 Gigabytes
Tamaño por Colección/Array: 2.620 elementos
------------------------------------------------------------
method DirectoryGetFiles - Elapsed Time: 00:00:0138 +
method MyComputerGetFiles - Elapsed Time: 00:00:0608 +++
method ElektroGetFiles - Elapsed Time: 00:00:0151 ++
Como puedes comprobar, mi implementación es altamente velóz cuanto mayor es la cantidad de archivos a analizar, y es casi igual de eficiente a la función
Directory.GetFiles() cuando se trata de una cantidad pequeña de archivos a analizar, con una diferencia ínfima de milisegundos... lo que hace que merezca mucho la pena usarlo si necesitamos buscar varias extensiones de archivo al mismo tiempo.
Bueno, y de la función
My.Computer.FileSystem.GetFiles mejor ni hablemos, los resultados hablan por si mismos. Los miembros expuestos en "
My.Computer" al igual que en
Microsoft.VisualBasic están muy poco optimizados y ningún programador de VB.NET al que le preocupe el rendimiento de su app debería usarlos. De hecho en el foro he repetido mil veces que los miembros del namespace
Microsoft.VisualBasic solo existen por temas de compatibilidad y conformidad por gente que migre de VB6 a VB.NET y lo tengan más facil para orientarse, que ningún programador de VB.NET debería utilizar el namespace
Microsoft.VisualBasic más que para mostrar un
MsgBox y listo xD, se creerán que hablo por hablar o algo... pues bueno, pueden ver por ustedes mismos el nefasto código fuente en la referencia online del source de .NET Framework.
PD: Estos tests se han realizado bajo circunstancias óptimas, realizando dos veces consecutivas cada llamada a cada uno de los tres métodos para que la caché de archivos enumerados del disco se actualizase y evitar así diferencias dispares en el tiempo de ejecución entre cada método.
Un saludo.
:o :o :o :o . mierrrrrrrr. todo eso lo creaste tu :o , la verdad me has dejado
impresionado . creo que yo nunca podría hacer algo así.
gracias de verdad por el code trabaja bien y es rápido. estoy en sorprendido. :o .
Gracias Elektro me fue de gran ayuda.
Cita de: **Aincrad** en 23 Septiembre 2017, 01:08 AM
:o :o :o :o . mierrrrrrrr. todo eso lo creaste tu :o , la verdad me has dejado
impresionado . creo que yo nunca podría hacer algo así.
Gracias, pero ese código no se merece mucha admiración, es viejito... le faltan varias revisiones de refactorización para tratar de optimizarlo más.
Me alegro de que te haya servido.
Saludos