【问题标题】:Zip from command line - how to trim path elements从命令行压缩 - 如何修剪路径元素
【发布时间】:2011-06-15 04:03:17
【问题描述】:

我正在使用 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 微妙之处的建议。

-----编辑

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

【问题讨论】:

    标签: cocoa zip nstask


    【解决方案1】:

    而不是

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

    【讨论】:

    • 这看起来是一个很好的解决方案,谢谢。我不知道我怎么错过了特定于任务的目录方法。自从我设法找到另一条路线以来,我还没有对此进行测试。我对此以及我提供的解决方案的另一个问题是,如果两个目录没有共同的父级怎么办?
    • @SG1 如果目录没有共同的父目录,我认为zip 命令行实用程序无法做到这一点。您可以将目录复制到某个目录,但这并不理想。
    【解决方案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);
    }
    

    再一次,我没有声称这是防弹的(并且希望改进),但它确实可以正确压缩任何单个文件夹。

    【讨论】:

      猜你喜欢
      • 2016-09-04
      • 1970-01-01
      • 2021-11-28
      • 1970-01-01
      • 2019-08-03
      • 1970-01-01
      • 2010-09-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多