How to resolve relative path in Objective-C?

I am trying to execute the code below to find out if I can get it to extend the absolute path for these locations so that I can use them for actions with NSFileManager that fail when I use the tilde and relative paths.

I am working on a command line application in Xcode in Objective-C. I can run the program from the command line, and it extends the path for me, but from the target in Xcode I pass the values ​​for the command line arguments using $ PROJECT_DIR and $ HOME to get part of the path from me. The trouble is that I need to get to $ PROJECT_DIR / .. which is not allowed using NSFilemanager.

It does not look like URLByResolvingSymlinksInPath or URLByStandardizingPath are working as I expect. Is there anything else I should do?

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"); } 

Update: I use the realpath from stdlib to resolve the path and created the following method, although I do not understand this C function. In particular, I do not know how much the value is resolved or how I will use it. I see to get the expected return value.

 - (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
source share
3 answers

Below is my solution that works well, which uses a lower level C function that I was trying to avoid. It works for my purposes. The full project that is being used is available on GitHub with the method that I created for Objective-C below.

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]; } 
+2
source

Of the paths in your example, only ~/ is the absolute path, so only ~/ can be turned into an absolute URL.

But alas, NSURL does not allow tilde ( ~ ) at all. You must use -[NSString stringByStandardizingPath] or -[NSString stringByExpandingTildeInPath] to expand the tilde.

Unable to convert . into an absolute URL without specifying which URL it refers to. NSURL does not just assume that you want to use the current process directory. You must be explicit.

For the same reason, it is impossible to resolve ..

You did not give this in your question, but in somename/.. it is impossible to allow .. because somename can become a symbolic link, and .. after executing a symbolic link, it can transfer you to a different directory than the one that contains somename .

Unfortunately, the NSURL documentation NSURL not mention these restrictions. NSString documentation .

You can get the current directory with -[NSFileManager currentDirectoryPath] , pass it to +[NSURL fileURLWithPath:] and pass the result (absolute file URL for the current directory) to +[NSURL URLWithString:relativeToURL:] for resolution . , .. , and symbolic links.

+8
source

Your sample paths are divided into two groups: tilde paths and "point" paths.

For tilde paths, you must extend them in your code, the tilde is not recognized by the file system, but is an abbreviation introduced by command line interpreters (otherwise called "shells", CLIs). To make an extension, you can use methods such as stringByExpandingTildeInPath .

The "point" paths are different, "." and ".." are located as part of the file system, and the paths containing them work.

However, the path starting with "." or ".." is relative to the current working directory (CWD). Although CWD is obvious to the CLI, it is less obvious that it can be configured for a GUI application, which means that although such paths work, they probably do not refer to what you expect from them after starting the GUI application. However, you can install CWD, see changeCurrentDirectoryPath: followed by paths starting with "." or ".." should refer to what you expect.

+2
source

Source: https://habr.com/ru/post/1489009/


All Articles