c# - Multiple file-extensions searchPattern para System.IO.Directory.GetFiles
.net (18)
¿Cuál es la sintaxis para configurar múltiples extensiones de archivo como searchPattern
en Directory.GetFiles()
? Por ejemplo, filtrando archivos con extensiones .aspx y .ascx .
// TODO: Set the string ''searchPattern'' to only get files with
// the extension ''.aspx'' and ''.ascx''.
var filteredFiles = Directory.GetFiles(path, searchPattern);
Actualización : LINQ no es una opción , tiene que ser un searchPattern
pasado a GetFiles
, como se especifica en la pregunta.
@ Daniel B, gracias por la sugerencia de escribir mi propia versión de esta función. Tiene el mismo comportamiento que Directory.GetFiles, pero admite el filtrado de expresiones regulares.
string[] FindFiles(FolderBrowserDialog dialog, string pattern)
{
Regex regex = new Regex(pattern);
List<string> files = new List<string>();
var files=Directory.GetFiles(dialog.SelectedPath);
for(int i = 0; i < files.Count(); i++)
{
bool found = regex.IsMatch(files[i]);
if(found)
{
files.Add(files[i]);
}
}
return files.ToArray();
}
Lo encontré útil, así que pensé que lo compartiría.
Creo que no hay una solución "lista para usar", eso es una limitación del método Directory.GetFiles.
Sin embargo, es bastante fácil escribir su propio método, aquí hay un example .
El código podría ser:
/// <summary> /// Returns file names from given folder that comply to given filters /// </summary> /// <param name="SourceFolder">Folder with files to retrieve</param> /// <param name="Filter">Multiple file filters separated by | character</param> /// <param name="searchOption">File.IO.SearchOption, /// could be AllDirectories or TopDirectoryOnly</param> /// <returns>Array of FileInfo objects that presents collection of file names that /// meet given filter</returns> public string[] getFiles(string SourceFolder, string Filter, System.IO.SearchOption searchOption) { // ArrayList will hold all file names ArrayList alFiles = new ArrayList(); // Create an array of filter string string[] MultipleFilters = Filter.Split(''|''); // for each filter find mathing file names foreach (string FileFilter in MultipleFilters) { // add found file names to array list alFiles.AddRange(Directory.GetFiles(SourceFolder, FileFilter, searchOption)); } // returns string array of relevant file names return (string[])alFiles.ToArray(typeof(string)); }
En lugar de la función EndsWith, elegiría utilizar el método Path.GetExtension()
lugar. Aquí está el ejemplo completo:
var filteredFiles = Directory.EnumerateFiles( path )
.Where(
file => Path.GetExtension(file).Equals( ".aspx", StringComparison.OrdinalIgnoreCase ) ||
Path.GetExtension(file).Equals( ".ascx", StringComparison.OrdinalIgnoreCase ) );
o:
var filteredFiles = Directory.EnumerateFiles(path)
.Where(
file => string.Equals( Path.GetExtension(file), ".aspx", StringComparison.OrdinalIgnoreCase ) ||
string.Equals( Path.GetExtension(file), ".ascx", StringComparison.OrdinalIgnoreCase ) );
(Utilice StringComparison.OrdinalIgnoreCase
si le importa el rendimiento: comparaciones de cadenas de MSDN )
GetFiles solo puede coincidir con un patrón único, pero puede usar Linq para invocar GetFiles con múltiples patrones:
FileInfo[] fi = new string[]{"*.txt","*.doc"}
.SelectMany(i => di.GetFiles(i, SearchOption.AllDirectories))
.ToArray();
Vea la sección de comentarios aquí: http://www.codeproject.com/KB/aspnet/NET_DirectoryInfo.aspx
Intentaré especificar algo como
var searchPattern = "as?x";
deberia de funcionar.
La solución fácil de recordar, floja y tal vez imperfecta:
Directory.GetFiles(dir, "*.dll").Union(Directory.GetFiles(dir, "*.exe"))
Me gusta este método, porque es legible y evita múltiples iteraciones del directorio:
var allowedExtensions = new [] {".doc", ".docx", ".pdf", ".ppt", ".pptx", ".xls", ".xslx"};
var files = Directory
.GetFiles(folder)
.Where(file => allowedExtensions.Any(file.ToLower().EndsWith))
.ToList();
Me temo que tendrás que hacer algo como esto, he mutado la expresión regular desde here .
var searchPattern = new Regex(
@"$(?<=/.(aspx|ascx))",
RegexOptions.IgnoreCase);
var files = Directory.GetFiles(path).Where(f => searchPattern.IsMatch(f));
Solo quisiera decir que si usa FileIO.FileSystem.GetFiles
lugar de Directory.GetFiles
, permitirá una matriz de comodines.
Por ejemplo:
Dim wildcards As String() = {"*.html", "*.zip"}
Dim ListFiles As List(Of String) = FileIO.FileSystem.GetFiles(directoryyouneed, FileIO.SearchOption.SearchTopLevelOnly, wildcards).ToList
Una forma más eficiente de obtener archivos con las extensiones ".aspx" y ".ascx" que evita consultar el sistema de archivos varias veces y evita devolver muchos archivos no deseados, es prefiltrar los archivos utilizando un patrón de búsqueda aproximado y para refinar el resultado después:
var filteredFiles = Directory.GetFiles(path, "*.as?x")
.Select(f => f.ToLowerInvariant())
.Where(f => f.EndsWith("px") || f.EndsWith("cx"))
.ToList();
Versión c # de la respuesta de @ qfactor77. Esta es la mejor manera sin LINQ.
string[] wildcards= {"*.mp4", "*.jpg"};
ReadOnlyCollection<string> filePathCollection = FileSystem.GetFiles(dirPath, Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories, wildcards);
string[] filePath=new string[filePathCollection.Count];
filePathCollection.CopyTo(filePath,0);
ahora devuelve la matriz de cadena de filePath
. Al principio necesitas
using Microsoft.VisualBasic.FileIO;
using System.Collections.ObjectModel;
también necesita agregar referencia a Microsoft.VisualBasic
Yo usaría lo siguiente:
var ext = new string[] { ".ASPX", ".ASCX" };
FileInfo[] collection = (from fi in new DirectoryInfo(path).GetFiles()
where ext.Contains(fi.Extension.ToUpper())
select fi)
.ToArray();
EDITAR: corregido desajuste entre Directorio y DirectoryInfo
mira como esta demostración:
void Main()
{
foreach(var f in GetFilesToProcess("c://", new[] {".xml", ".txt"}))
Debug.WriteLine(f);
}
private static IEnumerable<string> GetFilesToProcess(string path, IEnumerable<string> extensions)
{
return Directory.GetFiles(path, "*.*")
.Where(f => extensions.Contains(Path.GetExtension(f).ToLower()));
}
/// <summary>
/// Returns the names of files in a specified directories that match the specified patterns using LINQ
/// </summary>
/// <param name="srcDirs">The directories to seach</param>
/// <param name="searchPatterns">the list of search patterns</param>
/// <param name="searchOption"></param>
/// <returns>The list of files that match the specified pattern</returns>
public static string[] GetFilesUsingLINQ(string[] srcDirs,
string[] searchPatterns,
SearchOption searchOption = SearchOption.AllDirectories)
{
var r = from dir in srcDirs
from searchPattern in searchPatterns
from f in Directory.GetFiles(dir, searchPattern, searchOption)
select f;
return r.ToArray();
}
public static bool CheckFiles(string pathA, string pathB)
{
string[] extantionFormat = new string[] { ".war", ".pkg" };
return CheckFiles(pathA, pathB, extantionFormat);
}
public static bool CheckFiles(string pathA, string pathB, string[] extantionFormat)
{
System.IO.DirectoryInfo dir1 = new System.IO.DirectoryInfo(pathA);
System.IO.DirectoryInfo dir2 = new System.IO.DirectoryInfo(pathB);
// Take a snapshot of the file system. list1/2 will contain only WAR or PKG
// files
// fileInfosA will contain all of files under path directories
FileInfo[] fileInfosA = dir1.GetFiles("*.*",
System.IO.SearchOption.AllDirectories);
// list will contain all of files that have ..extantion[]
// Run on all extantion in extantion array and compare them by lower case to
// the file item extantion ...
List<System.IO.FileInfo> list1 = (from extItem in extantionFormat
from fileItem in fileInfosA
where extItem.ToLower().Equals
(fileItem.Extension.ToLower())
select fileItem).ToList();
// Take a snapshot of the file system. list1/2 will contain only WAR or
// PKG files
// fileInfosA will contain all of files under path directories
FileInfo[] fileInfosB = dir2.GetFiles("*.*",
System.IO.SearchOption.AllDirectories);
// list will contain all of files that have ..extantion[]
// Run on all extantion in extantion array and compare them by lower case to
// the file item extantion ...
List<System.IO.FileInfo> list2 = (from extItem in extantionFormat
from fileItem in fileInfosB
where extItem.ToLower().Equals
(fileItem.Extension.ToLower())
select fileItem).ToList();
FileCompare myFileCompare = new FileCompare();
// This query determines whether the two folders contain
// identical file lists, based on the custom file comparer
// that is defined in the FileCompare class.
return list1.SequenceEqual(list2, myFileCompare);
}
var filtered = Directory.GetFiles(path)
.Where(file => file.EndsWith("aspx", StringComparison.InvariantCultureIgnoreCase) || file.EndsWith("ascx", StringComparison.InvariantCultureIgnoreCase))
.ToList();
var filteredFiles = Directory
.EnumerateFiles(path, "*.*") // .NET4 better than `GetFiles`
.Where(
// ignorecase faster than tolower...
file => file.ToLower().EndsWith("aspx")
|| file.EndsWith("ascx", StringComparison.OrdinalIgnoreCase))
.ToList();
- No olvide el nuevo .NET4
Directory.EnumerateFiles
para un aumento del rendimiento ( ¿Cuál es la diferencia entre Directory.EnumerateFiles vs Directory.GetFiles? ) - "IgnoreCase" debería ser más rápido que "ToLower"
O bien, puede ser más rápido dividir y unir tus globs (al menos se ve más limpio):
"*.ext1;*.ext2".Split('';'')
.SelectMany(g => Directory.EnumerateFiles(path, g))
.ToList();
var filteredFiles = Directory
.GetFiles(path, "*.*")
.Where(file => file.ToLower().EndsWith("aspx") || file.ToLower().EndsWith("ascx"))
.ToList();
Editar 2014-07-23
Puede hacer esto en .NET 4.5 para una enumeración más rápida:
var filteredFiles = Directory
.EnumerateFiles(path) //<--- .NET 4.5
.Where(file => file.ToLower().EndsWith("aspx") || file.ToLower().EndsWith("ascx"))
.ToList();