I am using Xcode 6.4 trying to execute a find command. The application is a wrapper around the find command. We have a SAN that finder will not search however the find command will search the SAN, I don't wish to discuss the issues with the SAN.
I wrote the application originally in Swift in a few short minutes. Unfortunately it will not deploy to OSX 10.8 so I proceeded to rewrite in Objective C.
I suspect the problem I'm having is related to the way I am constructing the arguments array. The only examples I came across after Googling for 3 days all had hard coded literals for the arguments, in the real world we use variables.
Here is the basic code associated when I click the "Search" button.
NSString* newShell = @"-c";
NSString* commandFind = @"find";
NSString* optionName = @"-iname";
NSString* searchFor = @"\"";
NSString* searchPath = @"\"";
searchPath = [searchPath stringByAppendingString:_searchPathOutlet.stringValue];
searchPath = [searchPath stringByAppendingString:@"\""];
NSString* searchWildCard = @"*";
NSString* searchWord = _searchWordsOutlet.stringValue;
searchFor = [searchFor stringByAppendingString:searchWildCard];
searchFor = [searchFor stringByAppendingString:searchWord];
searchFor = [searchFor stringByAppendingString:searchWildCard];
searchFor = [searchFor stringByAppendingString:@"\""];
NSLog(@"%@",searchPath); //debug
NSLog(@"%@",searchFor); //debug
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/bin/sh"];
NSArray *arguments = [NSArray arrayWithObjects: newShell, commandFind, searchPath, optionName, searchFor, nil];
NSString *stringRep = [NSString stringWithFormat:@"%@",arguments]; //debug
NSLog(@"%@",stringRep); //debug
[task setArguments:arguments];
NSPipe* pipe = [NSPipe pipe];
[task setStandardOutput:pipe];
[task launch];
[task waitUntilExit]; // Alternatively, make it asynchronous.
NSData *outputData = [[pipe fileHandleForReading] readDataToEndOfFile];
NSString *outputString = [[NSString alloc] initWithData:outputData encoding:NSUTF8StringEncoding];
_searchResultsOutlet.string = outputString;
The output is as follows:
2015-07-16 12:09:39.141 APSAETVSANSearch[2716:68456] "/Users/test/Downloads"
2015-07-16 12:09:39.141 APSAETVSANSearch[2716:68456] "*adobe*"
2015-07-16 12:09:39.141 APSAETVSANSearch[2716:68456] (
"-c",
find,
"\"/Users/test/Downloads\"",
"-iname",
"\"*adobe*\""
)
usage: find [-H | -L | -P] [-EXdsx] [-f path] path ... [expression]
find [-H | -L | -P] [-EXdsx] -f path [path ...] [expression]
I agree with both you and trojanfoe. I am new to objective-c and I find the syntax a little strange compared to other languages but I have some working code listed below. I would like to run the function doSearch as a callback in an asynchronous thread. I am familiar with Microsoft's threading related to passing "thread safe" parameters using delegates to the thread's callback function (e.g. searchPathURL, searchWords, textView) but can't seem to find an example that is appropriate via google. Here is my function can you get me started?
- (IBAction)buttonSearch_Click:(id)sender {
doSearch(directoryURL, _searchWordOutlet.stringValue, _textViewOutlet);
}
void doSearch(NSURL *searchPathURL, NSString *searchWords, NSTextView *textView){
NSArray *keys = [NSArray arrayWithObjects:
NSURLIsDirectoryKey, NSURLIsPackageKey, NSURLLocalizedNameKey, nil];
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager]
enumeratorAtURL:directoryURL
includingPropertiesForKeys:keys
options:(NSDirectoryEnumerationSkipsHiddenFiles)
errorHandler:^(NSURL *url, NSError *error) {
// Handle the error.
// Return YES if the enumeration should continue after the error.
return YES;
}
];
for (NSURL *url in enumerator) {
// Error-checking is omitted for clarity.
NSNumber *isDirectory = nil;
[url getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:NULL];
if ([isDirectory boolValue]) {
NSString *localizedName = nil;
[url getResourceValue:&localizedName forKey:NSURLLocalizedNameKey error:NULL];
NSNumber *isPackage = nil;
[url getResourceValue:&isPackage forKey:NSURLIsPackageKey error:NULL];
if ([isPackage boolValue]) {
//Its a package
//NSLog(@"Package at %@", localizedName);
}
else {
//Its a directory
//NSLog(@"Directory at %@", localizedName);
}
}
else {
//Its a file
NSString *searchPath = [url.path lowercaseString];
NSString *searchText = [searchWords lowercaseString];
if ([searchPath containsString:searchText]) {
NSLog(@"%@", url.path);
[textView insertText:url.path];
[textView insertText:@"\n"];
}
}
}
}