Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Cocoa 从命令行压缩-如何修剪路径元素_Cocoa_Zip_Nstask - Fatal编程技术网

Cocoa 从命令行压缩-如何修剪路径元素

Cocoa 从命令行压缩-如何修剪路径元素,cocoa,zip,nstask,Cocoa,Zip,Nstask,我正在使用NSTask从我的应用程序中执行zip命令。它作为参数传递一些指向要压缩的文件/文件夹的路径 问题是,如果没有-j选项,最终的zip在zip中会出现荒谬的文件路径,如/private/var/folders/A5/A5CusLQaEo4mop reb SYE+++TI/-Tmp-/9101A216-5A6A-4CD6-A477-E4B86E007476-51228-00014BCB951432F/myfile.rtf。但是,如果我添加了-j选项,那么如果嵌套文件夹中的任何文件都有名称冲

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

问题是,如果没有-j选项,最终的zip在zip中会出现荒谬的文件路径,如/private/var/folders/A5/A5CusLQaEo4mop reb SYE+++TI/-Tmp-/9101A216-5A6A-4CD6-A477-E4B86E007476-51228-00014BCB951432F/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的微妙之处提出的建议

---编辑

我忘记添加的另一件事是,传递的原始目录是path,因此我认为期望的结果也是期望的结果。

而不是

[[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];
…
而不是

[[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];
…

这不是一个通用的解决方案,因为它不能很好地处理多个目录,但我用于未知内容的单个目录(即混合文件/文件夹/捆绑包)的解决方案是枚举目录的内容,并将其作为参数单独添加到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);
}

再次强调,我不主张这是防弹的,希望改进,但它确实可以正确压缩任何单个文件夹。

这不是一个通用的解决方案,因为它不能很好地处理多个目录,但我使用的解决方案是一个未知内容的目录,即,混合文件/文件夹/捆绑包是枚举目录的内容,并将它们作为参数单独添加到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);
}

同样,我也不声称这是防弹的,并且希望改进,但它确实可以正确压缩任何单个文件夹。

这看起来是一个很好的解决方案,谢谢。我不知道我怎么会错过特定于任务的目录方法。不过,自从我找到另一条路线以来,我还没有测试过这个。关于这一点,以及我提供的解决方案,我还有一个问题,那就是,如果这两个目录没有公共父目录怎么办?@SG1我认为如果这两个目录没有公共父目录,zip命令行实用程序无法做到这一点。您可以将目录复制到某个目录,尽管这并不理想。这看起来是一个很好的解决方案,谢谢。我不知道我怎么会错过特定于任务的目录方法。不过,自从我找到另一条路线以来,我还没有测试过这个。关于这一点,以及我提供的解决方案,我还有一个问题,那就是,如果这两个目录没有公共父目录怎么办?@SG1我认为如果这两个目录没有公共父目录,zip命令行实用程序无法做到这一点。您可以将目录复制到某个目录,尽管这并不理想。