Getting a list of files in a directory with a glob
Solution 1
You can achieve this pretty easily with the help of NSPredicate, like so:
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];
If you need to do it with NSURL instead it looks like this:
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];
Solution 2
This works quite nicely for IOS
, but should also work for 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);
}
}
Solution 3
What about using NSString's hasSuffix and hasPrefix methods? Something like (if you're searching for "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
}
}
For simple, straightforward matches like that it would be simpler than using a regex library.
Solution 4
Very Simplest Method:
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);
Solution 5
Unix has a library that can perform file globbing operations for you. The functions and types are declared in a header called glob.h
, so you'll need to #include
it. If open up a terminal an open the man page for glob by typing man 3 glob
you'll get all of the information you need to know to use the functions.
Below is an example of how you could populate an array the files that match a globbing pattern. When using the glob
function there are a few things you need to keep in mind.
- By default, the
glob
function looks for files in the current working directory. In order to search another directory you'll need to prepend the directory name to the globbing pattern as I've done in my example to get all of the files in/bin
. - You are responsible for cleaning up the memory allocated by
glob
by callingglobfree
when you're done with the structure.
In my example I use the default options and no error callback. The man page covers all of the options in case there's something in there you want to use. If you're going to use the above code, I'd suggest adding it as a category to NSArray
or something like that.
NSMutableArray* files = [NSMutableArray array];
glob_t gt;
char* pattern = "/bin/*";
if (glob(pattern, 0, NULL, >) == 0) {
int i;
for (i=0; i<gt.gl_matchc; i++) {
[files addObject: [NSString stringWithCString: gt.gl_pathv[i]]];
}
}
globfree(>);
return [NSArray arrayWithArray: files];
Edit: I've created a gist on github that contains the above code in a category called NSArray+Globbing.
sammich
Updated on July 08, 2022Comments
-
sammich almost 2 years
For some crazy reason I can't find a way to get a list of files with a glob for a given directory.
I'm currently stuck with something along the lines of:
NSString *bundleRoot = [[NSBundle mainBundle] bundlePath]; NSArray *dirContents = [[NSFileManager defaultManager] directoryContentsAtPath:bundleRoot];
..and then stripping out the stuff I don't want, which sucks. But what I'd really like is to be able to search for something like "foo*.jpg" instead of asking for the entire directory, but I've not been able to find anything like that.
So how the heck do you do it?
-
Nico over 14 years
stringWithCString:
is deprecated. The correct replacement is-[NSFileManager stringWithFileSystemRepresentation:length:]
, although I think most people usestringWithUTF8String:
(which is easier but not guaranteed to be the right encoding). -
Jonny over 13 yearsdirectoryContentsAtPath is deprecated since iOS 2.0. This question + answer are too old...
-
jksemple over 13 yearsJust went ahead and updated the code sample to use contentsOfDirectoryAtPath:error: rather than directoryContentsAtPath:
-
mtmurdock about 13 yearsthis looks great! is there a way to format the predicate to catch two file types at once, such as '.jpg' and '.png'?
-
jksemple about 13 yearsYeah, you can add additional logic using OR statements, e.g. "self ENDSWITH '.jpg' OR self ENDSWITH '.png'"
-
Cliff Ribaudo over 12 yearsThis is awesome... I have been pissing around with other approaches for a whole day now! Great. The main trick is just knowing what to search for on StackO!
-
Bruno Berisso about 12 yearsYou can use the "pathExtension == '.xxx'" instead of "ENDSWITH". Look this answer
-
Andrew about 10 years"pathExtension='.jpg'" should be "pathExtension='jpg'". If you include the '.' this doesn't work, pathExtension looks for everything after the '.'
-
Alex Cio about 10 yearsYou should use
contentsOfDirectoryAtPath:error:
instead ofdirectoryContentsAtPath
because itsdeprecated
sinceiOS
2.0 -
ssc over 9 yearsusing
@"self ENDSWITH '.jpg'"
with an NSURL fails withCan't do a substring operation with something that isn't a string
as the array contains URLs, not strings, but I can't seem to figure out how to elegantly transform every array item; probably also beyond the scope of the question... -
Guy almost 8 yearsThis is the first response in the list to answer the question, so I voted it up