I am trying to find the relative path of something not from root but from a given path instead, like find the difference of 2 paths using std::filesystem::path
objects, for example:
std::filesystem::path path = "/var/log", file = "/var/log/folder1/folder2/log.log";
I was expecting that operator-
was implemented for this kind of things so I was expecting something like:
std::filesystem::path rel = file - path; //With a expected result of "folder1/folder2/log.log"
EDIT: After some research and attempts, I finally managed to use std::mismatch
like this:
#include <filesystem>
#include <iostream>
#include <algorithm>
int main() {
std::filesystem::path path, file;
path = "/var/log";
file = "/var/log/folder1/folder2/log.log";
// Temporary string conversion
std::string path_str = path.string(), file_str = file.string();
std::filesystem::path str = std::string(std::mismatch(file_str.begin(), file_str.end(), path_str.begin()).first, file_str.end());
std::cout << "Relative path is " << str.relative_path() << std::endl;
return 0;
}
It will output: Relative path is "folder1/folder2/log.log"
My question is: Can the same be done without that temporary std::string
conversion?
CodePudding user response:
std::mismatch()
can help you finding common paths. I assumed there's always a shared path. Starting from the mismatched path element, you can append the rest paths.
Following code printed folde1/folder2/log.log
in vs2022.
#include <algorithm>
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
int main() {
try {
fs::path path = "/var/log";
fs::path file = "/var/log/folder1/folder2/log.log";
auto common = std::mismatch(path.begin(), path.end(), file.begin());
fs::path relative_path;
for (auto& iter = common.second; iter != file.end(); iter) {
relative_path /= *iter;
}
std::cout << relative_path.string() << std::endl;
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
return -1;
}
return 0;
}
CodePudding user response:
std::filesystem::relative
has an overload that accepts a base path and returns the first argument relative to the second, so all you need is:
auto relative_path = std::filesystem::relative(file, path);