Question

I've been struggling to find a solution to do what should be a very simple task. I need to move a certain type of file (all zip files in this case) into another directory. I've tried NSTask and NSFileManager but have come up empty. I can move one at a time, but I would like to move them in one shot, at the same time.

- (void)copyFilesTo :(NSString*)thisPath {

    NSFileManager *manager = [NSFileManager defaultManager];
    NSDirectoryEnumerator *direnum = [manager enumeratorAtPath:thisPath];
    NSString *filename = nil;

    while ((filename = [direnum nextObject] )) {

        if ([filename hasSuffix:@".zip"]) {

            [fileManager copyItemAtPath:thisPath toPath:newPath];

        }       
    }
}

FAILED - files copied = zeroooo

- (void)copyFilesMaybe :(NSString*)thisPath {

    newPath = [newPath stringByAppendingPathComponent:fileName];

    task = [[NSTask alloc] init];
    [task setLaunchPath: @"/usr/bin/find"];
    [task waitUntilExit];

    NSArray *arguments;

    arguments = [NSArray arrayWithObjects: thisPath, @"-name", @"*.zip", @"-exec", @"cp", @"-f", @"{}", newPath, @"\\", @";", nil];

    [task setArguments: arguments];

    NSPipe *pipe;
    pipe = [NSPipe pipe];
    [task setStandardOutput: pipe];

    NSFileHandle *file;
    file = [pipe fileHandleForReading];

    [task launch];

}

Same sad result, no files copied. What the heck am I doing wrong?

Was it helpful?

Solution

In the first case, you aren't using filename in your copy call. You need to construct a full path to the file by combining filename with thisPath and attempting to copy that. Also, the method is -copyItemAtPath:toPath:error:. You left off the last parameter. Try:

            NSError* error;
            if (![fileManager copyItemAtPath:[thisPath stringByAppendingPathComponent:filename] toPath:newPath error:&error])
                // handle error (at least log error)

In the second case, I think your arguments array is wrong. I'm not sure why it includes @"\\". I suspect because at a shell you have to escape the semicolon with a backslash (\;). However, the need to escape the semicolon is because the shell would otherwise interpret it and not pass it to find. Since you're not using a shell, you don't need to do that. (Also, if you did need to escape it, it shouldn't be a separate element of the arguments array. It would be in the same element as the semicolon, like @"\\;".)

Also, are you sure the task has completed? You show the launch but you don't show observing or waiting for its termination. Given that you've set a pipe for its output, you have to read from that pipe to be sure that the subprocess isn't getting stuck writing to it.

I'm not sure why you're calling -waitUntilExit before launching the task. That may be harmless, though.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top