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?
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);
Demo
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With