web-dev-qa-db-ja.com

globを使用してディレクトリ内のファイルのリストを取得する

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

私は現在、次の行に沿って何かに固執しています:

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

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

それで、あなたはそれをどのようにやっていますか?

134
sammich

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];
239
Brian Webster

これは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);            
    }       
}
32
Matt

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

    }
}

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

27
John Biesnecker

最も簡単な方法:

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

Unixには、ファイルグロビング操作を実行できるライブラリがあります。関数と型はglob.hというヘッダーで宣言されているため、#includeにする必要があります。ターミナルを開いてman 3 globと入力してglobのmanページを開くと、関数を使用するために知っておく必要のあるすべての情報が得られます。

以下は、グロビングパターンに一致するファイルを配列に取り込む方法の例です。 glob関数を使用する際には、留意する必要があることがいくつかあります。

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

この例では、デフォルトのオプションを使用し、エラーコールバックは使用しません。マニュアルページには、使用したいものがある場合に備えてすべてのオプションが記載されています。上記のコードを使用する場合は、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];

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

10
Bryan Kyle

不要なファイルを削除するには、独自のメソッドをロールする必要があります。

これは組み込みのツールでは簡単ではありませんが、 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; 
 @ end 
 
 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]]; 
 
 [pool drain]; 
 return 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); 
} 
}
@終わり
5
Mark

このトピックの専門家のふりをするつもりはありませんが、objective-cからglob関数とwordexp関数の両方にアクセスできる必要がありますか?

3
Sean Bright

stringWithFileSystemRepresentationは、iOSでは使用できないようです。

2
Oscar