i using xcode 6.4 trying execute find command. application wrapper around find command. have san finder not search find command search san, don't wish discuss issues san.
i wrote application in swift in few short minutes. unfortunately not deploy osx 10.8 proceeded rewrite in objective c.
i suspect problem i'm having related way constructing arguments array. examples came across after googling 3 days had hard coded literals arguments, in real world use variables.
here basic code associated when click "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 asynchronous. nsdata *outputdata = [[pipe filehandleforreading] readdatatoendoffile]; nsstring *outputstring = [[nsstring alloc] initwithdata:outputdata encoding:nsutf8stringencoding]; _searchresultsoutlet.string = outputstring; output 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 both , trojanfoe. new objective-c , find syntax little strange compared other languages have working code listed below. run function dosearch callback in asynchronous thread. familiar microsoft's threading related passing "thread safe" parameters using delegates thread's callback function (e.g. searchpathurl, searchwords, textview) can't seem find example appropriate via google. here function can 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 error. // return yes if enumeration should continue after error. return yes; } ]; (nsurl *url in enumerator) { // error-checking omitted 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 package //nslog(@"package @ %@", localizedname); } else { //its directory //nslog(@"directory @ %@", localizedname); } } else { //its file nsstring *searchpath = [url.path lowercasestring]; nsstring *searchtext = [searchwords lowercasestring]; if ([searchpath containsstring:searchtext]) { nslog(@"%@", url.path); [textview inserttext:url.path]; [textview inserttext:@"\n"]; } } } }
when use /bin/sh -c <command> command has 1 argument. is, @ shell, can't do:
/bin/sh -c find "/users/test/downloads" -iname "*adobe*" you have do:
/bin/sh -c 'find "/users/test/downloads" -iname "*adobe*"' so, make 1 single string content equivalent to:
nsstring* command = @"find \"/users/test/downloads\" -iname \"*adobe*\""; and use argument array equivalent @[ @"-c", command ].
alternatively, if don't need shell process string (and, in example, don't), should set task's launch path @"/usr/bin/find" , set arguments @[ @"/users/test/downloads", @"-iname", @"*adobe*" ]. using shell when don't need adds danger , inefficiency. example, if user enters "$(rm -rf ~)" in text field, unhappy when run task. less destructive more if directory path or search term contains double quote (") character.
all of said, concur trojanfoe should programmatically rather launching subprocess. if nsdirectoryenumerator doesn't work reason, can use posix/bsd apis.
update in response updated question:
to run task in background, can use grand central dispatch (gcd). example, -buttonsearch_click: method written this:
- (ibaction)buttonsearch_click:(id)sender { dispatch_async(dispatch_get_global_queue(dispatch_queue_priority_default, 0), ^{ dosearch(directoryurl, _searchwordoutlet.stringvalue, _textviewoutlet); }); } however, can't update gui background thread. so, dosearch() function needs shunt manipulation of text view main thread. can using code following:
dispatch_async(dispatch_get_main_queue(), ^{ [textview inserttext:url.path]; [textview inserttext:@"\n"]; }); by way, check if search term in path not same find command started does. you're checking whole path, including parent directories, while find command checked each item's file name. can file name nsurl requesting lastpathcomponent rather path.
also, case-insensitive check if 1 string contains another, should not lowercase boths strings , call -containsstring:. should use -localizedcaseinsensitivecontainsstring: without lowercasing manually. (or, if don't want locale-appropriate case-insensitivity, can use -rangeofstring:options: nscaseinsensitivesearch options.)
Comments
Post a Comment