5

我正在尝试下面的代码,看看我是否可以让它扩展这些位置的绝对路径,以便我可以将它们用于 NSFileManager 的操作,当我使用波浪号和相对路径时,这些操作会失败。

我正在使用 Objective-C 中的 Xcode 开发命令行应用程序。我可以从命令行运行该程序,它为我扩展了路径,但是从 Xcode 中的目标,我使用 $PROJECT_DIR 和 $HOME 传递命令行参数的值,以便让我参与其中。问题是我需要访问 $PROJECT_DIR/.. 这不是通过 NSFilemanager 解决的。

URLByResolvingSymlinksInPath 或 URLByStandardizingPath 似乎没有像我预期的那样工作。还有什么我应该做的吗?

BOOL isDir = TRUE;
for (NSString *path in @[@"~/", @".", @".."]) {
    NSURL *url = [[[NSURL URLWithString:path] URLByResolvingSymlinksInPath] URLByStandardizingPath];
    DebugLog(@"path: %@", url.absoluteString);
    DebugLog(@"Exists: %@", [[NSFileManager defaultManager] fileExistsAtPath:url.path isDirectory:&isDir] ? @"YES" : @"NO");
}

更新:我使用来自 stdlib 的 realpath 来解析路径并创建了以下方法,尽管我不理解这个 C 函数。具体来说,我不知道解析的值是什么或我将如何使用它。我确实看到了得到预期的返回值。

- (NSString *)resolvePath:(NSString *)path {
    NSString *expandedPath = [[path stringByExpandingTildeInPath] stringByStandardizingPath];
    const char *cpath = [expandedPath cStringUsingEncoding:NSUTF8StringEncoding];
    char *resolved = NULL;
    char *returnValue = realpath(cpath, resolved);

//    DebugLog(@"resolved: %s", resolved);
//    DebugLog(@"returnValue: %s", returnValue);

    return [NSString stringWithCString:returnValue encoding:NSUTF8StringEncoding];
}
4

3 回答 3

10

在您的示例中的路径中,only~/是绝对路径,因此 only~/可能会变成绝对 URL。

但是,唉,NSURL根本不解决波浪号(~)。您必须使用-[NSString stringByStandardizingPath]-[NSString stringByExpandingTildeInPath]扩展波浪号。

如果不指定相对于哪个 URL,就不可能转换.为绝对 URL。 NSURL不会仅仅假设你想使用进程的当前目录。你必须是明确的。

同样的原因也无法解决..

你没有在你的问题中给出这个,但是在 中somename/..,不可能解决..因为somename可能最终成为一个符号链接,并且..在跟随符号链接之后可能会将你带到一个不同的目录,而不是包含somename.

不幸的是,NSURL文档没有提到这些限制。NSString 文档确实如此。

您可以使用 获取当前目录-[NSFileManager currentDirectoryPath],将其传递给+[NSURL fileURLWithPath:],并将结果(file当前目录的绝对 URL)传递+[NSURL URLWithString:relativeToURL:]给以解析...和符号链接。

于 2013-06-30T23:09:47.533 回答
2

您的示例路径分为两组:波浪号路径和“点”路径。

对于波浪号路径,您必须在代码中扩展它们,波浪号不被文件系统识别,而是由命令行解释器(又名“shells”,CLI)引入的简写。要进行扩展,您可以使用诸如stringByExpandingTildeInPath.

“点”路径是不同的,“。” 和“..”目录条目作为文件系统的一部分存在,并且包含它们的路径有效。

但是,以“.”开头的路径。或“..”被视为相对于当前工作目录 (CWD)。虽然 CWD 对于 CLI 是显而易见的,但对于 GUI 应用程序可能设置的内容不太明显 - 这意味着尽管此类路径有效,但它们可能不会引用您在启动 GUI 应用程序后所做的预期。但是,您可以设置 CWD,请参阅changeCurrentDirectoryPath:,之后的路径以“.”开头。或“..”应该引用您的期望。

于 2013-06-30T23:06:26.880 回答
2

下面是我的解决方案,它运行良好,它使用了我试图避免的较低级别的 C 函数。它为我的目的而工作。使用的完整项目可以在 GitHub 上使用我为下面的 Objective-C 创建的方法获得。

https://github.com/brennanMKE/Xcode4CodeSnippets/tree/master/SnippetImporter

- (NSString *)resolvePath:(NSString *)path {
    NSString *expandedPath = [[path stringByExpandingTildeInPath] stringByStandardizingPath];
    const char *cpath = [expandedPath cStringUsingEncoding:NSUTF8StringEncoding];
    char *resolved = NULL;
    char *returnValue = realpath(cpath, resolved);

    if (returnValue == NULL && resolved != NULL) {
        printf("Error with path: %s\n", resolved);
        // if there is an error then resolved is set with the path which caused the issue
        // returning nil will prevent further action on this path
        return nil;
    }

    return [NSString stringWithCString:returnValue encoding:NSUTF8StringEncoding];
}
于 2013-07-10T21:29:04.280 回答