Lấy danh sách các tập tin trong một thư mục có toàn cầu


136

Vì một số lý do điên rồ, tôi không thể tìm cách lấy danh sách các tệp có toàn cầu cho một thư mục nhất định.

Tôi hiện đang bị mắc kẹt với một cái gì đó dọc theo dòng:

NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
NSArray *dirContents = [[NSFileManager defaultManager] 
                        directoryContentsAtPath:bundleRoot];

.. và sau đó tước bỏ những thứ tôi không muốn, nó thật tệ. Nhưng điều tôi thực sự thích là có thể tìm kiếm thứ gì đó như "foo * .jpg" thay vì yêu cầu toàn bộ thư mục, nhưng tôi không thể tìm thấy bất cứ thứ gì như vậy.

Vì vậy, làm thế quái nào bạn làm điều đó?


Câu trả lời của Brian Webster đã giúp tôi rất nhiều trong một vấn đề tương tự. stackoverflow.com/questions/5105250/
Wytchkraft

1
Chỉ cần lưu ý phụ cho bất cứ ai đọc điều này, bạn có thể giải quyết vấn đề này bằng cách chỉ cần đặt các tệp của bạn vào một thư mục stackoverflow.com/questions/1762836/ Kẻ
seo

Câu trả lời:


240

Bạn có thể đạt được điều này khá dễ dàng với sự trợ giúp của NSPredicate, như vậy:

NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
NSFileManager *fm = [NSFileManager defaultManager];
NSArray *dirContents = [fm contentsOfDirectoryAtPath:bundleRoot error:nil];
NSPredicate *fltr = [NSPredicate predicateWithFormat:@"self ENDSWITH '.jpg'"];
NSArray *onlyJPGs = [dirContents filteredArrayUsingPredicate:fltr];

Nếu bạn cần làm điều đó với NSURL thay vào đó, nó sẽ trông như thế này:

NSURL *bundleRoot = [[NSBundle mainBundle] bundleURL];
NSArray * dirContents = 
      [fm contentsOfDirectoryAtURL:bundleRoot
        includingPropertiesForKeys:@[] 
                           options:NSDirectoryEnumerationSkipsHiddenFiles
                             error:nil];
NSPredicate * fltr = [NSPredicate predicateWithFormat:@"pathExtension='jpg'"];
NSArray * onlyJPGs = [dirContents filteredArrayUsingPredicate:fltr];

2
thư mụcContentsAtPath không dùng nữa kể từ iOS 2.0. Câu hỏi + câu trả lời này quá cũ ...
Jonny

7
Chỉ cần tiếp tục và cập nhật mẫu mã để sử dụng nội dungOfDirectoryAtPath: error: thay vì thư mụcContentsAtPath:
Brian Webster

5
Vâng, bạn có thể thêm logic bổ sung bằng cách sử dụng các câu lệnh OR, ví dụ: "self ENDSWITH '.jpg' HOẶC self ENDSWITH '.png'"
Brian Webster

2
Điều này thật tuyệt vời ... Tôi đã đi khắp nơi với các phương pháp khác trong cả ngày nay! Tuyệt quá. Thủ thuật chính là chỉ cần biết những gì cần tìm kiếm trên StackO!
Cliff Ribaudo

3
Bạn có thể sử dụng "pathExtension == '.xxx'" thay vì "ENDSWITH". Hãy xem câu trả lời
Bruno Berisso

34

Điều này hoạt động khá độc đáo cho IOS, nhưng cũng nên làm việc cho cocoa.

NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
NSFileManager *manager = [NSFileManager defaultManager];
NSDirectoryEnumerator *direnum = [manager enumeratorAtPath:bundleRoot];
NSString *filename;

while ((filename = [direnum nextObject] )) {

    //change the suffix to what you are looking for
    if ([filename hasSuffix:@".data"]) {   

        // Do work here
        NSLog(@"Files in resource folder: %@", filename);            
    }       
}

28

Còn việc sử dụng các phương thức hasSuffix và hasPrefix của NSString thì sao? Một cái gì đó như (nếu bạn đang tìm kiếm "foo * .jpg"):

NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
NSArray *dirContents = [[NSFileManager defaultManager] directoryContentsAtPath:bundleRoot];
for (NSString *tString in dirContents) {
    if ([tString hasPrefix:@"foo"] && [tString hasSuffix:@".jpg"]) {

        // do stuff

    }
}

Đối với các kết hợp đơn giản, đơn giản như thế, nó sẽ đơn giản hơn so với sử dụng thư viện regex.


Bạn nên sử dụng contentsOfDirectoryAtPath:error:thay directoryContentsAtPathvì vì nó deprecatedkể từ iOS2.0
Alex Cio

Đây là câu trả lời đầu tiên trong danh sách để trả lời câu hỏi, vì vậy tôi đã bỏ phiếu cho nó
Guy

12

Phương pháp rất đơn giản:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, 
                                                     NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];

NSFileManager *manager = [NSFileManager defaultManager];
NSArray *fileList = [manager contentsOfDirectoryAtPath:documentsDirectory 
                                                 error:nil];
//--- Listing file by name sort
NSLog(@"\n File list %@",fileList);

//---- Sorting files by extension    
NSArray *filePathsArray = 
  [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:documentsDirectory  
                                                      error:nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF EndsWith '.png'"];
filePathsArray =  [filePathsArray filteredArrayUsingPredicate:predicate];
NSLog(@"\n\n Sorted files by extension %@",filePathsArray);

10

Unix có một thư viện có thể thực hiện các hoạt động toàn cầu hóa tệp cho bạn. Các chức năng và loại được khai báo trong một tiêu đề được gọi glob.h, vì vậy bạn sẽ cần đến #includenó. Nếu mở một thiết bị đầu cuối, hãy mở trang man cho toàn cầu bằng cách nhập man 3 globbạn sẽ nhận được tất cả thông tin bạn cần biết để sử dụng các chức năng.

Dưới đây là một ví dụ về cách bạn có thể điền vào một mảng các tệp khớp với mẫu hình cầu. Khi sử dụng globchức năng có một vài điều bạn cần lưu ý.

  1. Theo mặc định, globchức năng tìm kiếm các tệp trong thư mục làm việc hiện tại. Để tìm kiếm một thư mục khác, bạn cần phải thêm tên thư mục vào mẫu hình cầu như tôi đã thực hiện trong ví dụ của mình để lấy tất cả các tệp trong đó /bin.
  2. Bạn chịu trách nhiệm dọn dẹp bộ nhớ được phân bổ bằng globcách gọi globfreekhi bạn hoàn thành cấu trúc.

Trong ví dụ của tôi, tôi sử dụng các tùy chọn mặc định và không có cuộc gọi lại lỗi. Trang man bao gồm tất cả các tùy chọn trong trường hợp bạn muốn sử dụng cái gì đó trong đó. Nếu bạn sẽ sử dụng mã ở trên, tôi khuyên bạn nên thêm nó dưới dạng một danh mục NSArrayhoặc một cái gì đó tương tự.

NSMutableArray* files = [NSMutableArray array];
glob_t gt;
char* pattern = "/bin/*";
if (glob(pattern, 0, NULL, &gt) == 0) {
    int i;
    for (i=0; i<gt.gl_matchc; i++) {
        [files addObject: [NSString stringWithCString: gt.gl_pathv[i]]];
    }
}
globfree(&gt);
return [NSArray arrayWithArray: files];

Chỉnh sửa: Tôi đã tạo một ý chính trên github có chứa đoạn mã trên trong một danh mục có tên NSArray + Globbing .


stringWithCString:bị phản đối Sự thay thế chính xác là -[NSFileManager stringWithFileSystemRepresentation:length:], mặc dù tôi nghĩ rằng hầu hết mọi người sử dụng stringWithUTF8String:(dễ dàng hơn nhưng không được đảm bảo là mã hóa đúng).
Peter Hosey

5

Bạn cần cuộn phương thức của riêng bạn để loại bỏ các tệp bạn không muốn.

Điều này không dễ với các công cụ tích hợp, nhưng bạn có thể sử dụng RegExKit Lite để hỗ trợ tìm các phần tử trong mảng được trả về mà bạn quan tâm. Theo ghi chú phát hành, điều này sẽ hoạt động trong cả ứng dụng Cacao và Cacao-Touch.

Đây là mã demo tôi đã viết trong khoảng 10 phút. Tôi đã thay đổi <và> thành "vì chúng không hiển thị bên trong khối trước, nhưng nó vẫn hoạt động với dấu ngoặc kép. Có lẽ ai đó biết thêm về định dạng mã ở đây trên StackOverflow sẽ sửa lỗi này (Chris?).

Đây là một dự án mẫu tiện ích dòng lệnh "Công cụ nền tảng". Nếu tôi nhận được git daemon của mình và chạy trên máy chủ nhà tôi sẽ chỉnh sửa bài đăng này để thêm URL cho dự án.

#import "Foundation / Foundation.h"
#import "RegexKit / RegexKit.h"

@interface MTFileMatcher: NSObject 
{
}
- (void) getFilesMatchingRegEx: (NSString *) inRegex forPath: (NSString *) inPath;
@kết thúc

int main (int argc, const char * argv [])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // chèn mã vào đây ...
    MTFileMatcher * matcher = [[[MTFileMatcher alloc] init] autorelease];
    [trình so khớp getFilesMatchingRegEx: @ "^. + \\. [Jj] [Pp] [Ee]? [Gg] $" forPath: [@ "~ / Pictures" chuỗiByExpandingTildeInPath]];

    [cống hồ bơi];
    trả về 0;
}

@imâyation MTFileMatcher
- (void) getFilesMatchingRegEx: (NSString *) inRegex forPath: (NSString *) inPath;
{
    NSArray * filesAtPath = [[[NSFileManager defaultManager] thư mụcContentsAtPath: inPath] mảngByMatchingObjectsWithRegex: inRegex];
    NSEnumerator * itr = [filesAtPath objectEnumerator];
    NSString * obj;
    while (obj = [itr nextObject])
    {
        NSLog (obj);
    }
}
@kết thúc

3

Tôi sẽ không giả vờ là một chuyên gia về chủ đề này, nhưng bạn sẽ có quyền truy cập vào cả chức năng globwordexpchức năng từ mục tiêu-c, phải không?



0

Swift 5

Điều này làm việc cho ca cao

        let bundleRoot = Bundle.main.bundlePath
        let manager = FileManager.default
        let dirEnum = manager.enumerator(atPath: bundleRoot)


        while let filename = dirEnum?.nextObject() as? String {
            if filename.hasSuffix(".data"){
                print("Files in resource folder: \(filename)")
            }
        }

0

Swift 5 cho ca cao

        // Getting the Contents of a Directory in a Single Batch Operation

        let bundleRoot = Bundle.main.bundlePath
        let url = URL(string: bundleRoot)
        let properties: [URLResourceKey] = [ URLResourceKey.localizedNameKey, URLResourceKey.creationDateKey, URLResourceKey.localizedTypeDescriptionKey]
        if let src = url{
            do {
                let paths = try FileManager.default.contentsOfDirectory(at: src, includingPropertiesForKeys: properties, options: [])

                for p in paths {
                     if p.hasSuffix(".data"){
                           print("File Path is: \(p)")
                     }
                }

            } catch  {  }
        }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.