我正在尝试下面的代码,看看我是否可以扩展这些位置的绝对路径,以便我可以将它们用于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];
}
答案 0 :(得分:9)
在您的示例中的路径中,只有~/
是绝对路径,因此只有~/
可能会转换为绝对路径。
但是唉,NSURL
根本没有解决波浪号(~
)。您必须使用-[NSString stringByStandardizingPath]
或-[NSString stringByExpandingTildeInPath]
来扩展代字号。
如果不指定相对于哪个网址,则无法将.
转换为绝对网址。 NSURL
不会假设您想要使用进程的当前目录。你必须明确。
出于同样的原因,无法解决..
。
您没有在问题中提及此问题,但在somename/..
中,无法解析..
,因为somename
可能最终成为符号链接,{{1跟随符号链接后,您可能会转到与包含..
的目录不同的目录。
不幸的是,somename
文档没有提到这些限制。 NSString documentation确实如此。
您可以使用NSURL
获取当前目录,将其传递给-[NSFileManager currentDirectoryPath]
,并将结果(当前目录的绝对+[NSURL fileURLWithPath:]
URL)传递给file
解析+[NSURL URLWithString:relativeToURL:]
,.
和符号链接。
答案 1 :(得分:2)
您的示例路径分为两组:波浪路径和“点”路径。
对于波形路径,您必须在代码中展开它们,文本系统无法识别波浪号,但这是命令行解释器(也称为“shell”,CLI)引入的简写。要进行扩展,您可以使用stringByExpandingTildeInPath
。
“点”路径不同,“。”和“..”目录条目作为文件系统的一部分存在,包含它们的路径可以工作。
然而,路径以“。”开头。或“..”被视为相对于当前工作目录(CWD)。虽然CWD对于CLI来说是显而易见的,但是对于GUI应用程序来说它可能设置得不那么明显 - 这意味着虽然这些路径可行,但它们可能不会引用您在启动GUI应用程序后所期望的操作。但是,您可以设置CWD,请参阅changeCurrentDirectoryPath:
,在以“。”开头的路径之后。或“......”应该引用你的期望。
答案 2 :(得分: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];
}