scan pattern net for files example c# filesystems .net

pattern - search files folder c#



¿Se puede llamar a Directory.GetFiles() con múltiples filtros? (26)

¡Usar el patrón de búsqueda de GetFiles para filtrar la extensión no es seguro! Por ejemplo, tiene dos archivos Test1.xls y Test2.xlsx y desea filtrar el archivo xls utilizando el patrón de búsqueda * .xls, pero GetFiles devuelve ambos Test1.xls y Test2.xlsx. No estaba al tanto de esto y se produjo un error en la producción. entorno cuando algunos archivos temporales de repente se manejaron como archivos correctos. El patrón de búsqueda era * .txt y los archivos temporales se llamaron * .txt20181028_100753898 Por lo tanto, no se puede confiar en el patrón de búsqueda, también debe agregar controles adicionales en los nombres de archivo.

Estoy tratando de usar el método Directory.GetFiles() para recuperar una lista de archivos de varios tipos, como mp3 ''s y jpg ''s. He intentado los dos siguientes sin suerte:

Directory.GetFiles("C://path", "*.mp3|*.jpg", SearchOption.AllDirectories); Directory.GetFiles("C://path", "*.mp3;*.jpg", SearchOption.AllDirectories);

¿Hay una manera de hacer esto en una llamada?


Acabo de encontrar otra forma de hacerlo. Todavía no hay una sola operación, sino tirarlo para ver qué piensan los demás al respecto.

private void getFiles(string path) { foreach (string s in Array.FindAll(Directory.GetFiles(path, "*", SearchOption.AllDirectories), predicate_FileMatch)) { Debug.Print(s); } } private bool predicate_FileMatch(string fileName) { if (fileName.EndsWith(".mp3")) return true; if (fileName.EndsWith(".jpg")) return true; return false; }


Dejar

var set = new HashSet<string> { ".mp3", ".jpg" };

Entonces

Directory.GetFiles(path, "*.*", SearchOption.AllDirectories) .Where(f => set.Contains( new FileInfo(f).Extension, StringComparer.OrdinalIgnoreCase));

o

from file in Directory.GetFiles(path, "*.*", SearchOption.AllDirectories) from ext in set where String.Equals(ext, new FileInfo(file).Extension, StringComparison.OrdinalIgnoreCase) select file;


Espero que esto ayude a alguien:

//getting only playable Audio/Video Files from open dialog OpenFileDialog dlg = new OpenFileDialog(); dlg.Filter = ""All Media Files|*.wav;*.aac;*.wma;*.wmv;*.avi;*.mpg;*.mpeg;*.m1v;*.mp2;*.mp3;*.mpa;*.mpe;*.m3u;*.mp4;*.mov;*.3g2;*.3gp2;*.3gp;*.3gpp;*.m4a;*.cda;*.aif;*.aifc;*.aiff;*.mid;*.midi;*.rmi;*.mkv;*.WAV;*.AAC;*.WMA;*.WMV;*.AVI;*.MPG;*.MPEG;*.M1V;*.MP2;*.MP3;*.MPA;*.MPE;*.M3U;*.MP4;*.MOV;*.3G2;*.3GP2;*.3GP;*.3GPP;*.M4A;*.CDA;*.AIF;*.AIFC;*.AIFF;*.MID;*.MIDI;*.RMI;*.MKV"; dlg.ShowDialog();


Haga las extensiones que desee en una cadena, es decir, ".mp3.jpg.wma.wmf" y luego verifique si cada archivo contiene la extensión que desea. Esto funciona con .net 2.0 ya que no usa LINQ.

string myExtensions=".jpg.mp3"; string[] files=System.IO.Directory.GetFiles("C:/myfolder"); foreach(string file in files) { if(myExtensions.ToLower().contains(System.IO.Path.GetExtension(s).ToLower())) { //this file has passed, do something with this file } }

La ventaja de este enfoque es que puede agregar o eliminar extensiones sin editar el código, es decir, para agregar imágenes png, simplemente escriba myExtensions = ". Jpg.mp3.png".


La siguiente función busca en múltiples patrones, separados por comas. También puede especificar una exclusión, por ejemplo: "! Web.config" buscará todos los archivos y excluirá "web.config". Los patrones se pueden mezclar.

private string[] FindFiles(string directory, string filters, SearchOption searchOption) { if (!Directory.Exists(directory)) return new string[] { }; var include = (from filter in filters.Split(new char[] { '','' }, StringSplitOptions.RemoveEmptyEntries) where !string.IsNullOrEmpty(filter.Trim()) select filter.Trim()); var exclude = (from filter in include where filter.Contains(@"!") select filter); include = include.Except(exclude); if (include.Count() == 0) include = new string[] { "*" }; var rxfilters = from filter in exclude select string.Format("^{0}$", filter.Replace("!", "").Replace(".", @"/.").Replace("*", ".*").Replace("?", ".")); Regex regex = new Regex(string.Join("|", rxfilters.ToArray())); List<Thread> workers = new List<Thread>(); List<string> files = new List<string>(); foreach (string filter in include) { Thread worker = new Thread( new ThreadStart( delegate { string[] allfiles = Directory.GetFiles(directory, filter, searchOption); if (exclude.Count() > 0) { lock (files) files.AddRange(allfiles.Where(p => !regex.Match(p).Success)); } else { lock (files) files.AddRange(allfiles); } } )); workers.Add(worker); worker.Start(); } foreach (Thread worker in workers) { worker.Join(); } return files.ToArray(); }

Uso:

foreach (string file in FindFiles(@"D:/628.2.11", @"!*.config, !*.js", SearchOption.AllDirectories)) { Console.WriteLine(file); }


Me pregunto por qué hay tantas "soluciones" publicadas?

Si mi comprensión de los novatos sobre cómo funciona GetFiles es correcta, solo hay dos opciones y cualquiera de las soluciones anteriores se puede resumir en estas:

  1. GetFiles, luego filtre: Rápido, pero un asesino de memoria debido al almacenamiento de gastos generales hasta que se apliquen los filtros

  2. Filtrar mientras que GetFiles: más lentos son los filtros, pero el uso de memoria es bajo ya que no se almacena la sobrecarga.
    Esto se explica en una de las publicaciones anteriores con un impresionante punto de referencia: cada opción de filtro provoca una operación GetFile separada, por lo que la misma parte del disco duro se lee varias veces.

En mi opinión, la Opción 1) es mejor, pero usar SearchOption.AllDirectories en carpetas como C: / usaría grandes cantidades de memoria.
Por lo tanto, solo haría un sub-método recursivo que pase por todas las subcarpetas usando la opción 1)

Esto debería causar solo 1 operación GetFiles en cada carpeta y, por lo tanto, ser rápida (Opción 1), pero use solo una pequeña cantidad de memoria ya que los filtros se aplican después de cada lectura de subcarpetas -> la sobrecarga se elimina después de cada subcarpeta.

Por favor, corríjame si estoy equivocado. Soy como dije bastante nuevo en programación, pero quiero obtener una comprensión más profunda de las cosas para llegar a ser bueno en esto :)


No Intenta lo siguiente:

List<string> _searchPatternList = new List<string>(); ... List<string> fileList = new List<string>(); foreach ( string ext in _searchPatternList ) { foreach ( string subFile in Directory.GetFiles( folderName, ext ) { fileList.Add( subFile ); } } // Sort alpabetically fileList.Sort(); // Add files to the file browser control foreach ( string fileName in fileList ) { ...; }

Tomado de: http://blogs.msdn.com/markda/archive/2006/04/20/580075.aspx


No ... creo que tienes que hacer tantas llamadas como los tipos de archivos que quieras.

Yo mismo crearía una función tomando una matriz en cadenas con las extensiones que necesito y luego iteraré en esa matriz haciendo todas las llamadas necesarias. Esa función devolvería una lista genérica de los archivos que coincidan con las extensiones que había enviado.

Espero eso ayude.


No puedo usar el método .Where porque estoy programando en .NET Framework 2.0 (Linq solo es compatible con .NET Framework 3.5+).

El código a continuación no .CaB mayúsculas y minúsculas (por lo que .CaB o .cab también se incluirán en la lista).

string[] ext = new string[2] { "*.CAB", "*.MSU" }; foreach (string found in ext) { string[] extracted = Directory.GetFiles("C://test", found, System.IO.SearchOption.AllDirectories); foreach (string file in extracted) { Console.WriteLine(file); } }


No sé qué solución es mejor, pero uso esto:

String[] ext = "*.ext1|*.ext2".Split(''|''); List<String> files = new List<String>(); foreach (String tmp in ext) { files.AddRange(Directory.GetFiles(dir, tmp, SearchOption.AllDirectories)); }


O simplemente puede convertir la cadena de extensiones a Cadena ^

vector <string> extensions = { "*.mp4", "*.avi", "*.flv" }; for (int i = 0; i < extensions.size(); ++i) { String^ ext = gcnew String(extensions[i].c_str());; String^ path = "C://Users//Eric//Videos"; array<String^>^files = Directory::GetFiles(path,ext); Console::WriteLine(ext); cout << " " << (files->Length) << endl; }


Otra forma de usar Linq, pero sin tener que devolver todo y filtrar eso en la memoria.

var files = Directory.GetFiles("C://path", "*.mp3", SearchOption.AllDirectories).Union(Directory.GetFiles("C://path", "*.jpg", SearchOption.AllDirectories));

En realidad son 2 llamadas a GetFiles() , pero creo que es coherente con el espíritu de la pregunta y las devuelve en una sola palabra.


Para .NET 4.0 y versiones posteriores,

var files = Directory.EnumerateFiles("C://path", "*.*", SearchOption.AllDirectories) .Where(s => s.EndsWith(".mp3") || s.EndsWith(".jpg"));

Para versiones anteriores de .NET,

var files = Directory.GetFiles("C://path", "*.*", SearchOption.AllDirectories) .Where(s => s.EndsWith(".mp3") || s.EndsWith(".jpg"));

Edición: Por favor, lea los comentarios. La mejora que sugiere Paul Farry y el problema de memoria / rendimiento que Christian.K señala son muy importantes.


Qué pasa

string[] filesPNG = Directory.GetFiles(path, "*.png"); string[] filesJPG = Directory.GetFiles(path, "*.jpg"); string[] filesJPEG = Directory.GetFiles(path, "*.jpeg"); int totalArraySizeAll = filesPNG.Length + filesJPG.Length + filesJPEG.Length; List<string> filesAll = new List<string>(totalArraySizeAll); filesAll.AddRange(filesPNG); filesAll.AddRange(filesJPG); filesAll.AddRange(filesJPEG);


Qué tal esto:

private static string[] GetFiles(string sourceFolder, string filters, System.IO.SearchOption searchOption) { return filters.Split(''|'').SelectMany(filter => System.IO.Directory.GetFiles(sourceFolder, filter, searchOption)).ToArray(); }

Lo encontré aquí (en los comentarios): http://msdn.microsoft.com/en-us/library/wz42302f.aspx


Sé que es vieja pregunta pero LINQ: (.NET40 +)

var files = Directory.GetFiles("path_to_files").Where(file => Regex.IsMatch(file, @"^.+/.(wav|mp3|txt)$"));


Si está utilizando VB.NET (o importó la dependencia en su proyecto de C #), realmente existe un método conveniente que le permite filtrar múltiples extensiones:

Microsoft.VisualBasic.FileIO.FileSystem.GetFiles("C://path", Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories, new string[] {"*.mp3", "*.jpg"});

En VB.NET se puede acceder a este a través del espacio Mi-nombre:

My.Computer.FileSystem.GetFiles("C:/path", FileIO.SearchOption.SearchAllSubDirectories, {"*.mp3", "*.jpg"})

Desafortunadamente, estos métodos de conveniencia no admiten una variante evaluada perezosamente como lo hace Directory.EnumerateFiles() .


Si tiene una gran lista de extensiones para verificar, puede usar lo siguiente. No quería crear muchas declaraciones OR, así que modifiqué lo que escribió Lette.

string supportedExtensions = "*.jpg,*.gif,*.png,*.bmp,*.jpe,*.jpeg,*.wmf,*.emf,*.xbm,*.ico,*.eps,*.tif,*.tiff,*.g01,*.g02,*.g03,*.g04,*.g05,*.g06,*.g07,*.g08"; foreach (string imageFile in Directory.GetFiles(_tempDirectory, "*.*", SearchOption.AllDirectories).Where(s => supportedExtensions.Contains(Path.GetExtension(s).ToLower()))) { //do work here }


También hay una solución de descenso que parece no tener ninguna sobrecarga de memoria o rendimiento y ser bastante elegante:

string[] filters = new[]{"*.jpg", "*.png", "*.gif"}; string[] filePaths = filters.SelectMany(f => Directory.GetFiles(basePath, f)).ToArray();


Tuve el mismo problema y no pude encontrar la solución correcta, así que escribí una función llamada GetFiles:

/// <summary> /// Get all files with a specific extension /// </summary> /// <param name="extensionsToCompare">string list of all the extensions</param> /// <param name="Location">string of the location</param> /// <returns>array of all the files with the specific extensions</returns> public string[] GetFiles(List<string> extensionsToCompare, string Location) { List<string> files = new List<string>(); foreach (string file in Directory.GetFiles(Location)) { if (extensionsToCompare.Contains(file.Substring(file.IndexOf(''.'')+1).ToLower())) files.Add(file); } files.Sort(); return files.ToArray(); }

Esta función llamará a Directory.Getfiles() solo una vez.

Por ejemplo, llamar a la función de esta manera:

string[] images = GetFiles(new List<string>{"jpg", "png", "gif"}, "imageFolder");

EDITAR: para obtener un archivo con múltiples extensiones use este:

/// <summary> /// Get the file with a specific name and extension /// </summary> /// <param name="filename">the name of the file to find</param> /// <param name="extensionsToCompare">string list of all the extensions</param> /// <param name="Location">string of the location</param> /// <returns>file with the requested filename</returns> public string GetFile( string filename, List<string> extensionsToCompare, string Location) { foreach (string file in Directory.GetFiles(Location)) { if (extensionsToCompare.Contains(file.Substring(file.IndexOf(''.'') + 1).ToLower()) &&& file.Substring(Location.Length + 1, (file.IndexOf(''.'') - (Location.Length + 1))).ToLower() == filename) return file; } return ""; }

Por ejemplo, llamar a la función de esta manera:

string image = GetFile("imagename", new List<string>{"jpg", "png", "gif"}, "imageFolder");


en .NET 2.0 (sin Linq):

public static List<string> GetFilez(string path, System.IO.SearchOption opt, params string[] patterns) { List<string> filez = new List<string>(); foreach (string pattern in patterns) { filez.AddRange( System.IO.Directory.GetFiles(path, pattern, opt) ); } // filez.Sort(); // Optional return filez; // Optional: .ToArray() }

Entonces úsalo:

foreach (string fn in GetFilez(path , System.IO.SearchOption.AllDirectories , "*.xml", "*.xml.rels", "*.rels")) {}


para

var exts = new[] { "mp3", "jpg" };

Tú podrías:

public IEnumerable<string> FilterFiles(string path, params string[] exts) { return Directory .EnumerateFiles(path, "*.*") .Where(file => exts.Any(x => file.EndsWith(x, StringComparison.OrdinalIgnoreCase))); }

Pero el beneficio real de EnumerateFiles aparece cuando se dividen los filtros y se combinan los resultados:

public IEnumerable<string> FilterFiles(string path, params string[] exts) { return exts.Select(x => "*." + x) // turn into globs .SelectMany(x => Directory.EnumerateFiles(path, x) ); }

Se vuelve un poco más rápido si no tienes que convertirlos en exts = new[] {"*.mp3", "*.jpg"} (es decir, exts = new[] {"*.mp3", "*.jpg"} ya).

Evaluación de desempeño basada en la siguiente prueba de LinqPad (nota: el Perf simplemente repite el delegado 10000 veces) https://gist.github.com/zaus/7454021

(se volvió a publicar y extendió desde ''duplicado'', ya que esa pregunta no solicitó específicamente LINQ: searchPattern de extensiones de archivo múltiples para System.IO.Directory.GetFiles )


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


DirectoryInfo directory = new DirectoryInfo(Server.MapPath("~/Contents/")); //Using Union FileInfo[] files = directory.GetFiles("*.xlsx") .Union(directory .GetFiles("*.csv")) .ToArray();


List<string> FileList = new List<string>(); DirectoryInfo di = new DirectoryInfo("C://DirName"); IEnumerable<FileInfo> fileList = di.GetFiles("*.*"); //Create the query IEnumerable<FileInfo> fileQuery = from file in fileList where (file.Extension.ToLower() == ".jpg" || file.Extension.ToLower() == ".png") orderby file.LastWriteTime select file; foreach (System.IO.FileInfo fi in fileQuery) { fi.Attributes = FileAttributes.Normal; FileList.Add(fi.FullName); }