सिस्टम.IO.Directory.GetFiles के लिए एकाधिक फ़ाइल-एक्सटेंशन सर्चपार्टनर


140

स्थापित करने के लिए वाक्य रचना क्या है एकाधिक फ़ाइल-एक्सटेंशन के रूप में searchPatternपर Directory.GetFiles()? उदाहरण के लिए .aspx और .ascx एक्सटेंशन वाली फ़ाइलों को फ़िल्टर करना ।

// TODO: Set the string 'searchPattern' to only get files with
// the extension '.aspx' and '.ascx'.
var filteredFiles = Directory.GetFiles(path, searchPattern);

अपडेट : LINQ एक विकल्प नहीं है , यह एक हो गया है searchPatternमें पारित कर दिया GetFilesसवाल के रूप में विनिर्दिष्ट,।


मुझे नहीं लगता कि कोई है। या तो सभी फ़ाइलों को सूचीबद्ध करें और फिर मैन्युअल रूप से फ़िल्टर करें या एकाधिक खोजकर्ता पर एक यूनियन करें। लेकिन मुझे पूरा यकीन है कि मैंने एसओ पर यह सटीक सवाल पहले भी देखा है।
कोडइन्चोस


पहले यहां पूछा गया और जवाब दिया गया: stackoverflow.com/questions/163162/…
डेविड

जवाबों:


41

मेरा मानना ​​है कि "आउट ऑफ द बॉक्स" समाधान नहीं है, जो कि Directory.GetFiles विधि की एक सीमा है।

हालांकि अपनी खुद की विधि लिखना काफी आसान है, यहाँ एक उदाहरण है

कोड हो सकता है:

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

7
यह करने का एक बहुत ही अपर्याप्त तरीका है, क्योंकि आप प्रत्येक फ़िल्टर के लिए पूरी निर्देशिका को लूप करेंगे। इसके बजाय आपको प्रत्येक फ़ाइल की जांच करनी चाहिए यदि उसमें फ़िल्टर है तो सूची में जोड़ें। आप इस सूत्र में बताए गए उत्तर का उपयोग कर सकते हैं: stackoverflow.com/questions/3754118/…
ot0

190
var filteredFiles = Directory
    .GetFiles(path, "*.*")
    .Where(file => file.ToLower().EndsWith("aspx") || file.ToLower().EndsWith("ascx"))
    .ToList();

2014-07-23 को संपादित करें

आप इसे .NET 4.5 में तेज़ गणना के लिए कर सकते हैं:

var filteredFiles = Directory
    .EnumerateFiles(path) //<--- .NET 4.5
    .Where(file => file.ToLower().EndsWith("aspx") || file.ToLower().EndsWith("ascx"))
    .ToList();

Directory.EnumerateFiles MSDN में


5
@ मिरो वर्नारी: GetFilesरिटर्न string[]
jgauffin

4
आपको एन्ड्सविथ () तर्क से * हटाना चाहिए, यह वाइल्डकार्ड मैचों को नहीं करता है।
हंस पसंत

3
अगर फ़ाइल के एक्सटेंशन की तुलना करें तो यह 'जैसे मेल करेगा।' (फ़ाइल => नई FileInfo (फ़ाइल) ।Extension.Equals ("aspx")) || नया FileInfo (फ़ाइल) ।Extension.Equals ("। ascx") ) '
डेमिथ

3
Directory.EnumerateFilesएक प्रदर्शन को बढ़ावा देने के लिए नए
.NET4

6
और आप हमेशा के file.EndsWith("...", StringComparison.InvariantCultureIgnoreCase);बजाय उपयोग कर सकते हैंToLower
drzaus 19

30

GetFiles केवल एक पैटर्न से मेल खा सकते हैं, लेकिन आप कई पैटर्न के साथ GetFiles को आमंत्रित करने के लिए Linq का उपयोग कर सकते हैं:

FileInfo[] fi = new string[]{"*.txt","*.doc"}
    .SelectMany(i => di.GetFiles(i, SearchOption.AllDirectories))
    .ToArray();

यहाँ टिप्पणी अनुभाग देखें: http://www.codeproject.com/KB/aspnet/NET_DirectoryInfo.aspx


2
पैटर्न ओवरलैप होने पर वे टकरा जाएंगे। जैसे new string[]{"*.txt","filename.*"},। हालाँकि, कॉल Distinctवास्तव में इस समस्या को हल नहीं करता है, क्योंकि FileInfo ऑब्जेक्ट्स संदर्भ समानता का उपयोग करते हैं, न कि शब्दार्थ समानता। इसे या तो हटाकर Distinctया इसे पास करके तय किया जा सकता है IEqualityComparer<FileInfo>। पूर्व करने के लिए संपादित।
ब्रायन

मुझे लगता है कि SelectManyफिर से (और फिर से) एक ही फ़ाइल संरचना पर पुनरावृति होगी, इसलिए यह प्रदर्शन के मामले में उप-इष्टतम हो सकता है।
देजन

28

मुझे यह तरीका पसंद है, क्योंकि यह पठनीय है और निर्देशिका के कई पुनरावृत्तियों से बचा जाता है:

var allowedExtensions = new [] {".doc", ".docx", ".pdf", ".ppt", ".pptx", ".xls", ".xslx"}; 
var files = Directory
    .GetFiles(folder)
    .Where(file => allowedExtensions.Any(file.ToLower().EndsWith))
    .ToList();

2
मुझे यह बहुत अच्छा लगता है क्योंकि मुझे अपने एक्सटेंशन एरे को पार्स नहीं करना है और इसे रेगेक्स या अन्य मैनुअल काम में जोड़ना है। धन्यवाद!
इयान न्यूलैंड

@Jodrell, या बस एकHashSet<string>
Jodrell

HashSet <string> एक्सटेंशन के लिए एक सरणी के बजाय यहाँ कोई मतलब नहीं है, क्योंकि एक्सटेंशन की संख्या सीमित है और सरणी प्रत्येक फ़ाइल के लिए iterated हो जाती है, जब तक कि EndsWith () सही नहीं हो जाती। यदि विधि को बहुत बड़ी संख्या में एक्सटेंशन के प्रदर्शन के लिए ट्यून करने की आवश्यकता होती है, तो एक हैशसेट का उपयोग किया जा सकता है। प्रभावी होने के लिए, प्रत्येक फ़ाइल के विस्तार को एंड्सविथ () - विधि के बजाय स्पष्ट रूप से (विभाजित, फिर मैच) मिलान करना होगा। यह पठनीयता को नुकसान पहुंचाएगा और अधिकांश में कोई महत्वपूर्ण उपयोग नहीं होगा यदि सभी वास्तविक जीवन मामलों का उपयोग नहीं करते हैं। मैं वहाँ वापस समुदाय संपादित करें।
मार्क

15

मुझे डर है कि आपको इस तरह से कुछ करना होगा, मैंने यहां से रेगेक्स को म्यूट कर दिया

var searchPattern = new Regex(
    @"$(?<=\.(aspx|ascx))", 
    RegexOptions.IgnoreCase);
var files = Directory.EnumerateFiles(path)
    .Where(f => searchPattern.IsMatch(f))
    .ToList();

यह एक अच्छा तरीका प्रतीत होता है, लापता भाग में एक परीक्षण (कामकाजी) नियमित अभिव्यक्ति होती है
जूनियर मेहे

14
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();

या, अपने ग्लब्स को विभाजित करने और मर्ज करने के लिए यह तेज हो सकता है (कम से कम यह क्लीनर दिखता है):

"*.ext1;*.ext2".Split(';')
    .SelectMany(g => Directory.EnumerateFiles(path, g))
    .ToList();

और अधिक विवरण के साथ "मूल" प्रश्न पर
रिपॉस्टिंगिंग

6

आसान करने के लिए याद है, आलसी और शायद अपूर्ण समाधान:

Directory.GetFiles(dir, "*.dll").Union(Directory.GetFiles(dir, "*.exe"))

4

मैं निम्नलिखित का उपयोग करेगा:

var ext = new string[] { ".ASPX", ".ASCX" };
FileInfo[] collection = (from fi in new DirectoryInfo(path).GetFiles()
                         where ext.Contains(fi.Extension.ToUpper())
                         select fi)
                         .ToArray();

संपादित करें: डायरेक्टरी और डायरेक्टरीइन्फो के बीच सही मेल नहीं खाते


3

एक्सटेंशन के साथ फाइल प्राप्त करने का एक अधिक कुशल तरीका ".aspx" और ".ascx" है जो फ़ाइल सिस्टम को कई बार क्वेरी करने से बचता है और बहुत सारी अवांछित फ़ाइलों को वापस करने से बचता है, लगभग एक अनुमानित खोज पैटर्न का उपयोग करके फ़ाइलों को पूर्व फ़िल्टर करना है और बाद में परिणाम को परिष्कृत करने के लिए:

var filteredFiles = Directory.GetFiles(path, "*.as?x")
    .Select(f => f.ToLowerInvariant())
    .Where(f => f.EndsWith("px") || f.EndsWith("cx"))
    .ToList();

2

मैं कुछ निर्दिष्ट करने की कोशिश करूंगा

var searchPattern = "as?x";

यह काम करना चाहिए।


हा! मुझे डर था कि aspx और ascx भी समान था और इस तरह एक हैक-समाधान प्रस्तुत करेगा। मुझे कुछ सामान्य चाहिए।
सेब निल्सन

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

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

2

EndsWith फ़ंक्शन के बजाय, मैं Path.GetExtension()इसके बजाय विधि का उपयोग करना चुनूंगा । यहाँ पूर्ण उदाहरण है:

var filteredFiles = Directory.EnumerateFiles( path )
.Where(
    file => Path.GetExtension(file).Equals( ".aspx", StringComparison.OrdinalIgnoreCase ) ||
            Path.GetExtension(file).Equals( ".ascx", StringComparison.OrdinalIgnoreCase ) );

या:

var filteredFiles = Directory.EnumerateFiles(path)
.Where(
    file => string.Equals( Path.GetExtension(file), ".aspx", StringComparison.OrdinalIgnoreCase ) ||
            string.Equals( Path.GetExtension(file), ".ascx", StringComparison.OrdinalIgnoreCase ) );

( StringComparison.OrdinalIgnoreCaseयदि आप प्रदर्शन की परवाह करते हैं तो उपयोग करें : MSDN स्ट्रिंग तुलना )


1

इस डेमो की तरह देखो:

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

1
आपके पास Path.GetExtensionजो आप उपयोग कर सकते हैं।
जिगौफिन

1

@ दानिएल बी, इस समारोह का अपना संस्करण लिखने के सुझाव के लिए धन्यवाद। इसमें Directory.GetFiles के समान व्यवहार है, लेकिन रेगेक्स फ़िल्टरिंग का समर्थन करता है।

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

मुझे यह उपयोगी लगा, इसलिए मैंने सोचा कि मैं साझा करूँगा।


1

c #actor77 के उत्तर का # संस्करण। यह 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);

अब filePathस्ट्रिंग सरणी लौटें । शुरुआत में आपको जरूरत है

using Microsoft.VisualBasic.FileIO;
using System.Collections.ObjectModel;

आपको संदर्भ जोड़ने की भी आवश्यकता है Microsoft.VisualBasic


1

मैंने आपकी ज़रूरत के अनुसार कई एक्सटेंशनों के लिए एक सरल तरीका खोजा, और कोई टावलर (), RegEx, foreach के साथ ...

List<String> myExtensions = new List<String>() { ".aspx", ".ascx", ".cs" }; // You can add as many extensions as you want.
DirectoryInfo myFolder = new DirectoryInfo(@"C:\FolderFoo");
SearchOption option = SearchOption.TopDirectoryOnly; // Use SearchOption.AllDirectories for seach in all subfolders.
List<FileInfo> myFiles = myFolder.EnumerateFiles("*.*", option)
    .Where(file => myExtensions
    .Any(e => String.Compare(file.Extension, e, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase) == 0))
    .ToList();

.Net मानक 2.0 पर काम करना।


1

आप इसे इस तरह से कर सकते हैं

new DirectoryInfo(path).GetFiles().Where(Current => Regex.IsMatch(Current.Extension, "\\.(aspx|ascx)", RegexOptions.IgnoreCase)

प्रश्न में है: LINQ एक विकल्प नहीं है, इसलिए यह उत्तर उपयोगी नहीं है
Arci

0
var filtered = Directory.GetFiles(path)
    .Where(file => file.EndsWith("aspx", StringComparison.InvariantCultureIgnoreCase) || file.EndsWith("ascx", StringComparison.InvariantCultureIgnoreCase))
    .ToList();

कोड के लिए अतिरिक्त स्पष्टीकरण जोड़ें। यह ओपी को आपके उत्तर को बेहतर ढंग से समझने में मदद कर सकता है।
user2339071 19

-2

बस यह कहना चाहूंगा कि यदि आप FileIO.FileSystem.GetFilesइसके बजाय उपयोग करते हैंDirectory.GetFiles , तो यह वाइल्डकार्ड की एक सरणी की अनुमति देगा।

उदाहरण के लिए:

Dim wildcards As String() = {"*.html", "*.zip"}
Dim ListFiles As List(Of String) = FileIO.FileSystem.GetFiles(directoryyouneed, FileIO.SearchOption.SearchTopLevelOnly, wildcards).ToList

कोई कहां से अधिग्रहण करता है FileIO?
जोएल मार्टिनेज़

1
इसे विज़ुअल स्टूडियो (2015) में आपके परिवेश में पहले से ही शामिल किया जाना चाहिए। यह Microsoft.VisualBasic नाम स्थान का हिस्सा है। मेरे मामले में विजुअलबैसिक है क्योंकि यह मेरी पसंद की भाषा है।
qfactor77
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.