1

我正在使用 NSTask 从我的应用程序中执行 zip 命令。它作为参数传递一些指向要压缩的文件/文件夹的路径。

问题是,如果没有 -j 选项,最终的 zip 最终会在 zip 中出现荒谬的文件路径,(如 "/private/var/folders/A5/A5CusLQaEo4mop-reb-SYE+++TI/-Tmp-/9101A216- 5A6A-4CD6-A477-E4B86E007476-51228-00014BCB9514323F/myfile.rtf")。但是,如果我添加 -j 选项,那么如果嵌套文件夹深处的任何文件具有

我尝试在执行 NSTask 之前设置路径:

[[NSFileManager defaultManager] changeCurrentDirectoryPath:path];

希望 zip 的文档说的是实话:

默认情况下, zip 将存储完整路径(相对于当前目录

但这并没有按预期工作。调整 -j 和 -p 和 -r 的设置只会以不同的组合产生上述问题。

问题:

如何获取一组目录,例如

  • /some/long/path/sub1/file1.txt
  • /some/long/path/sub2/file1.txt

并将它们压缩成一个内容为

  • /sub1/file1.txt
  • /sub2/file1.txt

感谢您对 zip 的细微之处提供任何建议。

- - -编辑

我忘记添加的另一件事是传递的原始目录是“路径”,因此在我看来,期望的结果也是预期的结果。

4

2 回答 2

2

代替

[[NSFileManager defaultManager] changeCurrentDirectoryPath:path];

-[NSTask setCurrentDirectoryPath:]在启动任务之前使用。例如:

NSString *targetZipPath = @"/tmp/foo.zip";
NSArray *args = [NSArray arrayWithObjects:@"-r", targetZipPath,
    @"sub1", @"sub2", nil];
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/usr/bin/zip"];
[task setArguments:args];

// set path to be the parent directory of sub1, sub2
[task setCurrentDirectoryPath:path];
…
于 2011-06-15T05:08:28.290 回答
2

这不是一个通用的解决方案,因为它不能很好地处理多个目录,但我用于未知内容的单个目录(即混合文件/文件夹/包)的解决方案是枚举目录的内容并将它们单独添加为 zip 的参数,而不是一次简单地压缩整个目录。

具体来说:

+ (BOOL)zipDirectory:(NSURL *)directoryURL toArchive:(NSString *)archivePath;
{
//Delete existing zip
if ( [[NSFileManager defaultManager] fileExistsAtPath:archivePath] ) {
    [[NSFileManager defaultManager] removeItemAtPath:archivePath error:nil];
}

//Specify action
NSString *toolPath = @"/usr/bin/zip";

//Get directory contents
NSArray *pathsArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[directoryURL path] error:nil];

//Add arguments
NSMutableArray *arguments = [[[NSMutableArray alloc] init] autorelease];
[arguments insertObject:@"-r" atIndex:0];
[arguments insertObject:archivePath atIndex:0];
for ( NSString *filePath in pathsArray ) {
    [arguments addObject:filePath]; //Maybe this would even work by specifying relative paths with ./ or however that works, since we set the working directory before executing the command
    //[arguments insertObject:@"-j" atIndex:0];
}

//Switch to a relative directory for working.
NSString *currentDirectory = [[NSFileManager defaultManager] currentDirectoryPath]; 
[[NSFileManager defaultManager] changeCurrentDirectoryPath:[directoryURL path]];
//NSLog(@"dir %@", [[NSFileManager defaultManager] currentDirectoryPath]);

//Create
NSTask *task = [[[NSTask alloc] init] autorelease];
[task setLaunchPath:toolPath];
[task setArguments:arguments];

//Run
[task launch];
[task waitUntilExit];

//Restore normal path
[[NSFileManager defaultManager] changeCurrentDirectoryPath:currentDirectory];

//Update filesystem
[[NSWorkspace sharedWorkspace] noteFileSystemChanged:archivePath];

return ([task terminationStatus] == 0);
}

同样,我没有声称这是防弹的(并且会喜欢改进),但它确实可以正确压缩任何单个文件夹。

于 2011-06-15T15:46:24.057 回答