Re: Recursive file remove
Re: Recursive file remove
- Subject: Re: Recursive file remove
- From: Tom Jones <email@hidden>
- Date: Sat, 14 Aug 2010 11:28:25 -0700
Thanks, this helps a lot. What I'm looking to "remove" is my temp directory where I'm downloading files un-compressing them etc. Just good house keeping.
I must admit having not been doing this long, and after Kyle's remark on "collected consulting fees" I'm surprised that there isn't a task as part of NSFileManager to remove items recursively like "removeItemAtPath:recursive:error:" for example. I mean Mac OS X is over 10 years old. :-)
Thanks,
tom
On Aug 14, 2010, at 8:02 AM, Jerry Krinock wrote:
> As noted, your choices are either NSFileManager methods of BSD/POSIX functions. I would tend to start with the latter because, at the end of the week, NSFileManager might not have the configurability you need to handle the nitty-gritty like system "dot" or "dot dot" files, (not) following symbolic links, etc. etc. But it may be just a personal preference. NSFileManager has not always been my friend.
>
> If you go the BSD route, also consider fts_open(), fts_read(), fts_close() since these handle the recursion for you. A few weeks ago I wrote a demo/template using these which is pasted in below. Because fts_read returns directories first followed by their descendants, you'd need to create an array and then "remove" items in reverse order, using appropriate functions for regular files vs. directories.
>
> And as Don Quixote implied, you need to think about exactly what you mean by "remove".
>
>
> #include <fts.h>
>
> int doSomething(char * const path) {
> printf("Doing %s\n", path) ;
> return 0 ;
> }
>
> int doSomething_recursive(char * const path) {
> // See man fts(3) for these. Modify these to do what you want:
> int fts_options = FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV | FTS_SEEDOT ;
>
> // fts_open requires a null-terminated array of paths.
> // We only have one path.
> char* paths[2] ;
> paths[0] = path ;
> paths[1] = NULL ;
>
> FTS* ftsp = fts_open(paths, fts_options, NULL) ;
> if (ftsp == NULL) {
> return -2 ;
> }
>
> FTSENT* ftsPointer = 0 ;
> while ((ftsPointer = fts_read(ftsp)) != NULL) {
> /*
> This will execute once for each item in the tree.
> According to the man page fts(3):
> "directories are visited two distinguishable times; in pre-order
> (before any of their descendants are visited) and in post-order
> (after all of their descendants have been visited)"
> But my doSomething() only logs once for each directory, in pre-order. Example:
> Doing /Users/jk/Desktop/OW5/.
> Doing /Users/jk/Desktop/OW5/..
> Doing /Users/jk/Desktop/OW5/BkmxTemp/.
> Doing /Users/jk/Desktop/OW5/BkmxTemp/..
> Doing /Users/jk/Desktop/OW5/BkmxTemp/placesNo1Dump.txt
> Doing /Users/jk/Desktop/OW5/BkmxTemp/placesOk1Dump.txt
> Apparently a "visit" does not mean "returned by ftsPointer->fts_info"
> */
> int result ;
> switch (ftsPointer->fts_info) {
> // List here the file types you want to doSomething to.
> // Again, see man fts(3).
> case FTS_D: // directory
> case FTS_F: // regular file
> case FTS_DOT: // system dot file, i.e. '.' or '..'
> case FTS_SL: // symbolic link
> result = doSomething(ftsPointer->fts_path) ;
> if (result != 0) {
> // Break out due to error
> return result ;
> }
> break ;
>
> default:
> break;
> }
> }
>
> fts_close(ftsp) ;
>
> return 0 ;
> }
>
> int main (int argc, const char * argv[]) {
> doSomething_recursive("/Users/jk/Desktop/OW5") ;
> return 0 ;
> }
>
> _______________________________________________
>
> Cocoa-dev mailing list (email@hidden)
>
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden