Translating an absolute path to a path relative to the current directory
Hi, I am running into the following problem these days: I need to translate an absolute path to a path relative to the current directory on Windows. The translation process need to include all required ".." directory specifiers in the path to make sure it can be accessed from the current directory. The following path samples may clarify the problem. -------------------------------------------------------------------------------- Current Directory: C:\x\y\z Absolute Path: C:\x\y\z\k\w.txt Translated Path: k\w.txt (C:\x\y\z is a common parent) Current Directory: C:\x\y\z Absolute Path: D:\a\b\c\d.txt Translated Path: D:\a\b\c\d.txt (no common parent found) Current Directory: C:\x\y\z Absolute Path: C:\x\k\w.txt Translated Path: ..\..\k\w.txt (C:\x is a common parent) -------------------------------------------------------------------------------- Is there any built-in support in the boost filesystem library to achieve such translation? At first I thought the path::relative_path could solve my problem but it does not seem to take into account the current directory, only the path itself. Any sugestion? Thanks in advance. Hermann
Hermann Rodrigues wrote:
Hi,
I am running into the following problem these days:
I need to translate an absolute path to a path relative to the current directory on Windows. The translation process need to include all required ".." directory specifiers in the path to make sure it can be accessed from the current directory.
Try this... path relative_to_current(path p) { path current = current_path(); // Trivial case if(equivalent(current, p)) return p; // Doesn't share a root if(!equivalent(current.root_path(), p.root_path())) return p; // We don't care about the root anymore // (and makes the rest easier) current = current.relative_path(); p = p.relative_path(); path final(".", native); path::iterator pit = p.begin(), cit = current.begin(); // Find the shared directory for(;pit != p.end() && cit != current.end(); ++pit, ++cit) if(*pit != *cit) // May not be right break; // Put needed parent dirs in while(cit != current.end()) { final = ".." / final; ++cit; } // Add the path from shared while(pit != p.end()) // Gah! Why doesn't *path::iterator return paths? final /= path(*pit++, native); // .normalize()? return final; } Haven't tested it too extensively, but it seems to work. Probably better as relative_path(path from, path to), but hey. -- don't quote this
Thank you for you reply.
I was currently using PathToRelativePath on Windows, pointed by
Gottlob Frege. However, your solution is portable and also seems to
work a Linux environment.
I will definitely try it.
Regards,
Hermann
On 11/3/05, Simon Buchan
Try this...
path relative_to_current(path p) { path current = current_path();
// Trivial case if(equivalent(current, p)) return p;
// Doesn't share a root if(!equivalent(current.root_path(), p.root_path())) return p;
// We don't care about the root anymore // (and makes the rest easier) current = current.relative_path(); p = p.relative_path();
path final(".", native);
path::iterator pit = p.begin(), cit = current.begin(); // Find the shared directory for(;pit != p.end() && cit != current.end(); ++pit, ++cit) if(*pit != *cit) // May not be right break;
// Put needed parent dirs in while(cit != current.end()) { final = ".." / final; ++cit; }
// Add the path from shared while(pit != p.end()) // Gah! Why doesn't *path::iterator return paths? final /= path(*pit++, native);
// .normalize()? return final; }
Haven't tested it too extensively, but it seems to work. Probably better as relative_path(path from, path to), but hey.
-- don't quote this
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (2)
-
Hermann Rodrigues
-
Simon Buchan