2011-06-15 51 views
1

我使用NSTask从我的应用程序执行zip命令。它作为参数传递了一些指向要压缩的文件/文件夹的路径。从命令行拉链 - 如何修剪路径元素

的问题是,如果没有-j选项,最终拉链拉链内结束了荒谬的文件路径,(如“/私人的/ var /文件夹/ A5/A5CusLQaEo4mop-REB-SYE +++ TI/-tmp -/9101A216-5A6A-4CD6-A477-E4B86E007476-51228-00014BCB9514323F/myfile.rtf“)。不过,如果我添加了-j选项,然后我不断碰到名称冲突,如果任何文件的任何地方内心深处一个嵌套的文件夹中有

我已经试过执行NSTask之前设置的路径:

[[NSFileManager defaultManager] changeCurrentDirectoryPath:path]; 

在希望为ZIP文件说的是真话:

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

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

问题:

我怎么能采取像一组目录

  • /some/long/path/sub1/file1.txt
  • /一些/长/路径/ SUB2 /文件1 .TXT

,并压缩它们成zip,其内容是

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

感谢对拉链的微妙之处任何建议。

-----编辑

一个我忘了补充另一件事是,正在传递的原始目录是“路径”,所以期望的结果也使我想起了预期的结果。

回答

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); 
} 

同样,我并没有要求这是防弹(并希望改进),但它的工作在正确荏苒任何一个文件夹。

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]; 
… 
+0

这看起来像一个很好的解决方案,谢谢。我不知道我错过了特定于任务的目录方法。自从我设法找到另一条路线以来,我还没有测试过这个。另一个关于这个问题以及我提供的解决方案的问题是,如果两个目录没有共同的父目录,该怎么办? – SG1 2011-06-15 15:52:38

+0

@ SG1我不认为'zip'命令行工具可以做到这一点,如果目录没有共同的父母。您可以将目录复制到某个目录,尽管这并不理想。 – 2011-06-15 21:45:58