グロブを含むディレクトリ内のファイルのリストを取得する


136

何かおかしな理由で、特定のディレクトリのグロブを含むファイルのリストを取得する方法が見つかりません。

私は現在、次の線に沿って何かで立ち往生しています:

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

..そして、私が欲しくないものを取り除いて、それはうんざりです。しかし、私が本当に望んでいるのは、ディレクトリ全体を要求する代わりに、「foo * .jpg」のようなものを検索できることですが、そのようなものを見つけることができませんでした。

一体どうやってやるの?


ブライアンウェブスターの回答は、同様の問題で多くの助けとなりました。stackoverflow.com/questions/5105250/...
Wytchkraft

1
これを読んでいる人へのメモとして、ファイルをフォルダに入れるだけで解決できるかもしれません。stackoverflow.com
questions / 1762836 /

回答:


240

NSPredicateを使用すると、次のようにかなり簡単にこれを実現できます。

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

代わりにNSURLを使用する必要がある場合は、次のようになります。

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
directoryContentsAtPathはiOS 2.0以降廃止されました。この質問と回答は古すぎます...
ジョニー

7
ちょうどは先に行って、contentsOfDirectoryAtPathを使用するコードサンプルを更新:エラー:というよりdirectoryContentsAtPath:
ブライアン・ウェブスター

5
ええ、ORステートメントを使用して追加のロジックを追加できます。たとえば、「self ENDSWITH '.jpg' OR self ENDSWITH '.png'」
Brian Webster

2
これはすごいです...私は1日中、他のアプローチにうんざりしています!すごい。主なトリックは、StackOで何を検索するかを知ることです。
Cliff Ribaudo 2012年

3
「ENDSWITH」の代わりに「pathExtension == '.xxx'」を使用できます。この答えを
ブルーノベリッソ

34

これはに対してIOSはうまく機能しますが、に対しても機能するはずです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

NSStringのhasSuffixおよびhasPrefixメソッドの使用についてはどうですか?次のようなもの(「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

    }
}

このような単純で単純な一致の場合、正規表現ライブラリを使用するよりも簡単です。


2.0 以降なので、contentsOfDirectoryAtPath:error:代わりに使用する必要がありますdirectoryContentsAtPathdeprecatediOS
Alex Cio

これは質問に答えるためのリストの最初の応答なので、投票しました
Guy

12

最も簡単な方法:

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には、ファイルグロビング操作を実行できるライブラリがあります。関数と型はと呼ばれるヘッダーで宣言されているglob.hので、必要に#includeなります。ターミナルを開くか、入力してglobのmanページを開くとman 3 glob、関数の使用に必要なすべての情報が得られます。

以下は、グロビングパターンに一致するファイルを配列に挿入する方法の例です。このglob関数を使用する場合、いくつかの点に注意する必要があります。

  1. デフォルトでは、glob関数は現在の作業ディレクトリでファイルを検索します。別のディレクトリを検索するには、例で行ったように、ディレクトリ名をグロビングパターンの前に付加して、内のすべてのファイルを取得する必要があります/bin
  2. 構造を使い終わったらglob、呼び出しによって割り当てられたメモリをクリーンアップするglobfree必要があります。

私の例では、デフォルトのオプションを使用し、エラーコールバックは使用しません。manページには、使用したいものがあれば、すべてのオプションが記載されています。上記のコードを使用する場合は、カテゴリNSArrayまたはそのようなものとして追加することをお勧めします。

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

編集:上記のコードをNSArray + Globbingというカテゴリに含むgithubの要旨を作成しました。


stringWithCString:廃止予定です。正しい置換はですが-[NSFileManager stringWithFileSystemRepresentation:length:]、ほとんどの人が使用していると思いますstringWithUTF8String:(これは簡単ですが、正しいエンコーディングであるとは限りません)。
Peter Hosey、2010

5

不要なファイルを削除するには、独自の方法を実行する必要があります。

これは組み込みのツールでは簡単ではありませんが、RegExKit Liteを使用して、関心のある返された配列内の要素を見つけるのを支援できます。リリースノートによると、これはCocoaアプリケーションとCocoa-Touchアプリケーションの両方で機能するはずです。

ここに私が約10分で書いたデモコードがあります。<と>を "に変更しました。これらはpreブロック内に表示されなかったためですが、引用符で機能します。StackOverflowでのコードのフォーマットの詳細を知っている人が修正するかもしれません(Chris?)。

これは「Foundation Tool」コマンドラインユーティリティテンプレートプロジェクトです。gitデーモンをホームサーバーで実行している場合は、この投稿を編集してプロジェクトのURLを追加します。

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

@interface MTFileMatcher:NSObject 
{
}
-(void)getFilesMatchingRegEx:(NSString *)inRegex forPath:(NSString *)inPath;
@終わり

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

    //ここにコードを挿入...
    MTFileMatcher * matcher = [[[MTFileMatcher alloc] init] autorelease];
    [matcher getFilesMatchingRegEx:@ "^。+ \\。[Jj] [Pp] [Ee]?[Gg] $" forPath:[@ "〜/ Pictures" stringByExpandingTildeInPath]];

    [プール排水];
    0を返します。
}

@implementation MTFileMatcher
-(void)getFilesMatchingRegEx:(NSString *)inRegex forPath:(NSString *)inPath;
{
    NSArray * filesAtPath = [[[NSFileManager defaultManager] directoryContentsAtPath:inPath] arrayByMatchingObjectsWithRegex:inRegex];
    NSEnumerator * itr = [filesAtPath objectEnumerator];
    NSString * obj;
    while(obj = [itr nextObject])
    {
        NSLog(obj);
    }
}
@終わり

3

私は、トピックに関する専門家のふりをしませんが、あなたは、両方へのアクセスが必要globwordexpなし、Objective-Cのから関数を?



0

スウィフト5

これはココアのために働きます

        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

        // 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  {  }
        }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.