Opened 10 years ago

Closed 2 years ago

#1976 closed Feature Requests (fixed)

Inverse function for complete

Reported by:… Owned by: Beman Dawes
Milestone: Boost 1.60.0 Component: filesystem
Version: Boost 1.35.0 Severity: Problem
Keywords: Cc: taylor@…, boost@…


As mentioned in the '[boost] [filesystem] "leaf"' thread, complete is the only path composition function without a corresponding decomposition function.

The idea: uncomplete(/foo/new, /foo/bar) => ../new

The use case for this is any time you get a full path (from an open dialog, perhaps) and want to store a relative path so that the group of files can be moved to a different directory without breaking the paths. An IDE would be a simple example, so that the project file could be safely checked out of subversion.

I'd like to call it relative, but that conceptually conflicts with the relative_path member decomposition function. Perhaps the member function could be changed to local_path(), or something.

A discussion will need to be held to determine expected behaviour in the presence of symlinks, since root/foo/bar/.. is not always root/foo.

Attachments (0)

Change History (16)

comment:1 Changed 9 years ago by…

An additional use case for this came up on the users list:

The use case here is creating complete output paths for "copy-pasting a sub-tree from input_base_path to output_base_path" (ofcourse with some transformations along the way).

For now, I am using

  fs::wpath output_path=output_base_path;
  int k=0; for(fs::wpath::iterator
i=input_path.begin();i!=input_path.end();i++,k++) if(k>=7)

Again, 7 is the number of elements in input_base_path. advance() would make it atleast slightly cleaner (remove k, and the if on k), uncomplete would be ideal.

comment:2 Changed 9 years ago by anonymous

Here's a naive implementation (that doesn't handle symlinks and isn't well tested):

#include <boost/filesystem.hpp>

naive_uncomplete(boost::filesystem::path const path, boost::filesystem::path const base) {
    if (path.has_root_path()){
        if (path.root_path() != base.root_path()) {
            return path;
        } else {
            return naive_uncomplete(path.relative_path(), base.relative_path());
    } else {
        if (base.has_root_path()) {
            throw "cannot uncomplete a path relative path from a rooted base";
        } else {
            typedef boost::filesystem::path::const_iterator path_iterator;
            path_iterator path_it = path.begin();
            path_iterator base_it = base.begin();
            while ( path_it != path.end() && base_it != base.end() ) {
                if (*path_it != *base_it) break;
                ++path_it; ++base_it;
            boost::filesystem::path result;
            for (; base_it != base.end(); ++base_it) {
                result /= "..";
            for (; path_it != path.end(); ++path_it) {
                result /= *path_it;
            return result;

comment:3 in reply to:  description Changed 9 years ago by anonymous

I would like this functionality to be added as well. My use case is similar to the first one mentioned (wanting to persist relative paths).

comment:4 Changed 9 years ago by anonymous

Getting paths relative to an arbitrary directory is a very useful feature. My use case is the same at the first one (it is an IDE which needs to store paths relative to project file).

comment:5 Changed 8 years ago by tom@…

I would like this for a media application which should save lines in an M3U playlist as filepaths relative to the playlist path.

comment:6 Changed 7 years ago by anonymous

This would be useful for me as well.

comment:7 Changed 7 years ago by anonymous

This feature would be very useful for us, too. In a use case similar to the first one.

comment:8 Changed 7 years ago by sorokin@…

Is there any plans to include this function is boost? Maybe under name relativize?

comment:9 Changed 6 years ago by Taylor Braun-Jones <taylor@…>

Cc: taylor@… added

comment:10 Changed 5 years ago by anonymous

I'm interested in this feature too.

comment:11 Changed 5 years ago by Chris Pick <boost@…>

Cc: boost@… added

comment:12 Changed 4 years ago by anonymous

There a quite a few links on the internet linking here. This would be a great feature. I'd wonder how to make this portable though with drive letters on windows, reparse points, symlinks on *nix...

comment:13 Changed 4 years ago by anonymous

There's an example at , it relies only on lexicographic compare so doesn't handle links etc, but on the other hand I think the expected behavior of such a function is that it's entirely lexicographic on the path.

comment:14 Changed 3 years ago by slowriot <riot@…>

+1 for this as well

comment:15 Changed 2 years ago by anonymous

I also need this!

comment:16 Changed 2 years ago by Beman Dawes

Milestone: Boost 1.36.0Boost 1.60.0
Resolution: fixed
Status: newclosed

Boost 1.60.0 will add functions lexically_normal, lexically_relative, relative, and weakly_canonical. These are designed to provide the functionality requested by this ticket.

See for more information. It proposes additional lexical and operational proximate functions, but I have chosen not to include those now. They will be reconsidered once users get some field experience with the core functionality for computing relative paths.

These function are available now on the develop branch, and will be merged to master as soon as sufficient regression tests have cycled. They will also be proposed for inclusion in the next version of the C++ committee's TS 18822, File System Technical Specification.

Many thanks to Jamie Allsop for his help and perseverance, and to everyone else who made suggestions and comments. Jamie's paper is available at



Modify Ticket

Change Properties
Set your email in Preferences
as closed The owner will remain Beman Dawes.
The resolution will be deleted.

Add Comment

E-mail address and name can be saved in the Preferences.

Note: See TracTickets for help on using tickets.