Hướng dẫn dùng dir tree trong PHP

answer

466

Hướng dẫn dùng dir tree trong PHP

Đối với .NET 4.0 trở lên,

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

Đối với các phiên bản trước của .NET,

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

chỉnh sửa: Xin vui lòng đọc các ý kiến. Sự cải thiện mà Paul Farry gợi ý, và vấn đề về trí nhớ / hiệu suất mà Christian.K chỉ ra đều rất quan trọng.

466 hữu ích 5 bình luận chia sẻ

answer

52

Còn cái này thì sao:

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

Tôi tìm thấy nó ở đây (trong các ý kiến): http://msdn.microsoft.com/en-us/l Library / wz42302f.aspx

52 hữu ích 5 bình luận chia sẻ

answer

29

Nếu bạn có một danh sách lớn các tiện ích mở rộng để kiểm tra, bạn có thể sử dụng các mục sau. Tôi không muốn tạo ra nhiều câu lệnh OR vì vậy tôi đã sửa đổi những gì lette đã viết.

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
}

29 hữu ích 5 bình luận chia sẻ

answer

27

cho

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

Bạn có thể:

public IEnumerable FilterFiles(string path, params string[] exts) {
    return
        Directory
        .EnumerateFiles(path, "*.*")
        .Where(file => exts.Any(x => file.EndsWith(x, StringComparison.OrdinalIgnoreCase)));
}
  • Đừng quên .NET4 mới Directory.EnumerateFilesđể tăng hiệu suất ( Sự khác biệt giữa Directory.Enum CảFiles so với Directory.GetFiles là gì? )
  • "IgnoreCase" phải nhanh hơn "ToLower" ( .EndsWith("aspx", StringComparison.OrdinalIgnoreCase)chứ không phải .ToLower().EndsWith("aspx"))

Nhưng lợi ích thực sự của việc EnumerateFileshiển thị khi bạn tách các bộ lọc và hợp nhất các kết quả:

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

Sẽ nhanh hơn một chút nếu bạn không phải biến chúng thành những khối u (tức là exts = new[] {"*.mp3", "*.jpg"}đã có).

Đánh giá hiệu suất dựa trên thử nghiệm LinqPad sau đây (lưu ý: Perfchỉ cần lặp lại 10000 lần đại biểu) https://gist.github.com/zaus/7454021

(đăng lại và mở rộng từ 'trùng lặp' vì câu hỏi đó đặc biệt yêu cầu không có LINQ: Nhiều phần mở rộng tệp tìm kiếm Mô hình cho System.IO.Directory.GetFiles )

27 hữu ích 5 bình luận chia sẻ

answer

15

Tôi biết đó là câu hỏi cũ nhưng LINQ: (.NET40 +)

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

15 hữu ích 1 bình luận chia sẻ

answer

11

Một cách khác để sử dụng Linq, nhưng không phải trả lại mọi thứ và lọc trên đó trong bộ nhớ.

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

Đó thực sự là 2 cuộc gọi GetFiles(), nhưng tôi nghĩ nó phù hợp với tinh thần của câu hỏi và trả lại chúng trong một số lượng lớn.

11 hữu ích 2 bình luận chia sẻ

answer

9

Ngoài ra còn có một giải pháp gốc mà dường như không có bất kỳ bộ nhớ hoặc hiệu năng nào và khá thanh lịch:

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

9 hữu ích 2 bình luận chia sẻ

answer

7

Không. Hãy thử như sau:

List _searchPatternList = new List();
    ...
    List fileList = new List();
    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 )
    {
        ...;
    }

Lấy từ: http://bloss.msdn.com/markda/archive/2006/04/20/580075.aspx

7 hữu ích 0 bình luận chia sẻ

answer

6

Để cho

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

Sau đó

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

hoặc là

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

6 hữu ích 1 bình luận chia sẻ

answer

5

Tôi không thể sử dụng .Wherephương pháp vì tôi đang lập trình trong .NET Framework 2.0 (Linq chỉ được hỗ trợ trong .NET Framework 3.5+).

Mã dưới đây không phân biệt chữ hoa chữ thường (vì vậy .CaBhoặc .cabsẽ được liệt kê quá).

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

5 hữu ích 0 bình luận chia sẻ

answer

4

Hàm sau tìm kiếm trên nhiều mẫu, được phân tách bằng dấu phẩy. Bạn cũng có thể chỉ định loại trừ, ví dụ: "! Web.config" sẽ tìm kiếm tất cả các tệp và loại trừ "web.config". Các mẫu có thể được trộn lẫn.

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 files = new List();

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

}

Sử dụng:

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

4 hữu ích 0 bình luận chia sẻ

answer

4

List FileList = new List();
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);
}

4 hữu ích 4 bình luận chia sẻ

answer

3

Chỉ cần tìm một cách khác để làm điều đó. Vẫn không phải là một thao tác, nhưng ném nó ra để xem người khác nghĩ gì về nó.

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

3 hữu ích 0 bình luận chia sẻ

answer

3

Thế còn

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 filesAll = new List(totalArraySizeAll);
filesAll.AddRange(filesPNG);
filesAll.AddRange(filesJPG);
filesAll.AddRange(filesJPEG);

3 hữu ích 0 bình luận chia sẻ

answer

2

Tạo các phần mở rộng bạn muốn một chuỗi tức là ".mp3.jpg.wma.wmf" và sau đó kiểm tra xem mỗi tệp có chứa phần mở rộng bạn muốn không. Điều này hoạt động với .net 2.0 vì nó không sử dụng 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

   }
}

Ưu điểm của phương pháp này là bạn có thể thêm hoặc xóa tiện ích mở rộng mà không cần chỉnh sửa mã tức là để thêm hình ảnh png, chỉ cần viết myExtensions = ". Jpg.mp3.png".

2 hữu ích 1 bình luận chia sẻ

answer

2

/// 
/// Returns the names of files in a specified directories that match the specified patterns using LINQ
/// 
/// The directories to seach
/// the list of search patterns
/// 
/// The list of files that match the specified pattern
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 hữu ích 0 bình luận chia sẻ

answer

2

Không ... Tôi tin rằng bạn phải thực hiện nhiều cuộc gọi như loại tệp bạn muốn.

Tôi sẽ tự tạo một hàm lấy một chuỗi trên các chuỗi với các phần mở rộng tôi cần và sau đó lặp lại trên mảng đó để thực hiện tất cả các cuộc gọi cần thiết. Hàm đó sẽ trả về một danh sách chung các tệp khớp với các tiện ích mở rộng tôi đã gửi.

Hy vọng nó giúp.

2 hữu ích 0 bình luận chia sẻ

answer

2

trong .NET 2.0 (không có Linq):

public static List GetFilez(string path, System.IO.SearchOption opt,  params string[] patterns)
{
    List filez = new List();
    foreach (string pattern in patterns)
    {
        filez.AddRange(
            System.IO.Directory.GetFiles(path, pattern, opt)
        );
    }


    // filez.Sort(); // Optional
    return filez; // Optional: .ToArray()
}

Sau đó sử dụng nó:

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

2 hữu ích 0 bình luận chia sẻ

answer

2

DirectoryInfo directory = new DirectoryInfo(Server.MapPath("~/Contents/"));

//Using Union

FileInfo[] files = directory.GetFiles("*.xlsx")
                            .Union(directory
                            .GetFiles("*.csv"))
                            .ToArray();

2 hữu ích 1 bình luận chia sẻ

answer

1

Tôi gặp vấn đề tương tự và không thể tìm ra giải pháp phù hợp nên tôi đã viết một hàm có tên GetFiles:

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

Chức năng này sẽ Directory.Getfiles()chỉ gọi một lần.

Ví dụ gọi hàm như thế này:

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

EDIT: Để có được một tệp có nhiều tiện ích mở rộng, hãy sử dụng tệp này:

/// 
    /// Get the file with a specific name and extension
    /// 
    /// the name of the file to find
    /// string list of all the extensions
    /// string of the location
    /// file with the requested filename
    public string GetFile( string filename, List 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 "";
    }

Ví dụ gọi hàm như thế này:

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

1 hữu ích 0 bình luận chia sẻ

answer

1

Tôi tự hỏi tại sao có rất nhiều "giải pháp" được đăng?

Nếu hiểu biết về tân binh của tôi về cách GetFiles hoạt động là đúng, chỉ có hai tùy chọn và bất kỳ giải pháp nào ở trên có thể được đưa ra dưới đây:

  1. GetFiles, sau đó lọc: Nhanh, nhưng trình diệt bộ nhớ do lưu trữ trên đầu cho đến khi các bộ lọc được áp dụng

  2. Lọc trong khi GetFiles: Làm chậm các bộ lọc hơn được đặt, nhưng mức sử dụng bộ nhớ thấp vì không có chi phí nào được lưu trữ.
    Điều này được giải thích trong một trong những bài viết trên với điểm chuẩn ấn tượng: Mỗi tùy chọn bộ lọc gây ra hoạt động GetFile riêng biệt để cùng một phần của ổ cứng được đọc nhiều lần.

Theo tôi, Tùy chọn 1) tốt hơn, nhưng sử dụng SearchOption.AllDirectories trên các thư mục như C: \ sẽ sử dụng một lượng lớn bộ nhớ.
Do đó tôi sẽ chỉ thực hiện một phương thức đệ quy đi qua tất cả các thư mục con bằng cách sử dụng tùy chọn 1)

Điều này chỉ gây ra 1 hoạt động GetFiles trên mỗi thư mục và nhanh chóng (Tùy chọn 1), nhưng chỉ sử dụng một lượng bộ nhớ nhỏ vì các bộ lọc được áp dụng sau mỗi lần đọc của thư mục con -> chi phí bị xóa sau mỗi thư mục con.

Xin hãy sửa tôi nếu tôi sai. Tôi như tôi đã nói khá mới về lập trình nhưng muốn hiểu sâu hơn về mọi thứ để cuối cùng trở nên giỏi về việc này :)

1 hữu ích 0 bình luận chia sẻ

answer

0

Tôi không biết giải pháp nào tốt hơn, nhưng tôi sử dụng giải pháp này:

String[] ext = "*.ext1|*.ext2".Split('|');

            List<String> files = new List<String>();
            foreach (String tmp in ext)
            {
                files.AddRange(Directory.GetFiles(dir, tmp, SearchOption.AllDirectories));
            }

0 hữu ích 0 bình luận chia sẻ

answer

0

Nếu bạn đang sử dụng VB.NET (hoặc nhập phụ thuộc vào dự án C # của bạn), thực sự tồn tại một phương thức tiện lợi cho phép lọc nhiều tiện ích mở rộng:

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

Trong VB.NET, điều này có thể được truy cập thông qua không gian tên của tôi:

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

Thật không may, các phương pháp tiện lợi này không hỗ trợ một biến thể được đánh giá lười biếng như thế Directory.EnumerateFiles().

0 hữu ích 0 bình luận chia sẻ

answer

0

Sử dụng mẫu tìm kiếm GetFiles để lọc tiện ích mở rộng không an toàn !! Chẳng hạn, bạn có hai tệp Test1.xls và Test2.xlsx và bạn muốn lọc tệp xls bằng mẫu tìm kiếm * .xls, nhưng GetFiles trả về cả Test1.xls và Test2.xlsx Tôi không biết điều này và đã gặp lỗi khi sản xuất môi trường khi một số tập tin tạm thời đột nhiên được xử lý như tập tin bên phải. Mẫu tìm kiếm là * .txt và các tệp tạm thời được đặt tên * .txt20181028_100753898 Vì vậy, mẫu tìm kiếm không thể tin cậy được, bạn cũng phải thêm kiểm tra tên tệp.

0 hữu ích 0 bình luận chia sẻ

answer

1

Hoặc bạn chỉ có thể chuyển đổi chuỗi tiện ích mở rộng thành Chuỗi ^

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

1 hữu ích 1 bình luận chia sẻ

answer

2

hy vọng điều này sẽ giúp ai đó:

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

2 hữu ích 1 bình luận chia sẻ