从命令行 Zip - 如何修剪路径元素

发布于 2024-11-16 00:03:04 字数 907 浏览 4 评论 0原文

我正在使用 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

的 zip 中

  • 并将它们压缩到内容为/sub1/file1.txt
  • /sub2/file1.txt

感谢您对 zip 的微妙之处提出的任何建议。

-----编辑

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

I'm executing a zip command from within my app using NSTask. It's passed as arguments some paths which point to the files/folders to be zipped.

The problem is that without the -j option, the final zip ends up with absurd filepaths inside the zip, (like "/private/var/folders/A5/A5CusLQaEo4mop-reb-SYE+++TI/-Tmp-/9101A216-5A6A-4CD6-A477-E4B86E007476-51228-00014BCB9514323F/myfile.rtf"). However, if I add the -j option, then I constantly run into name collisions if any file anywhere deep inside a nested folder has

I've tried setting the path before executing the NSTask:

[[NSFileManager defaultManager] changeCurrentDirectoryPath:path];

In the hope that the documentation for zip was telling the truth:

By default, zip will store the full path
(relative to the current directory)

But this did not work as expected. Adjusting settings of -j and -p and -r simply produces the above mentioned problems in different combinations.

QUESTION:

How can I take a set of directories like

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

and zip them into a zip whose contents are

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

Thanks for any advice on the subtleties of zip.

-----EDIT

One other thing I forgot to add is that the original directory being passed is "path", so the desired outcome is also to my mind the expected outcome.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

庆幸我还是我 2024-11-23 00:03:04

而不是

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

Instead of

[[NSFileManager defaultManager] changeCurrentDirectoryPath:path];

use -[NSTask setCurrentDirectoryPath:] prior to launching the task. For example:

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];
…
甜心小果奶 2024-11-23 00:03:04

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

同样,我并不声称这是万无一失的(并且希望进行改进),但它确实可以正确压缩任何单个文件夹。

This is not a universal solution, in that it won't handle multiple directories well, but the solution I'm using for a single directory of unknown contents (ie, mixed files/folders/bundles) is to enumerate the contents of the directory and add them individually as arguments to zip, rather than simply zipping the entire directory at once.

Specifically:

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

Again, I make no claims this is bulletproof (and would love improvements) but it does work at correctly zipping any single folder.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文