I'm trying to use std::filesystem::current_path()
to change the working directory to something that might be a symlink. If the target is a symlink, the link is getting resolved and the working directory becomes the target of the link rather than the path I specified. My main issue with this is it makes relative paths incorrect.
As an example:
#include <filesystem>
#include <iostream>
using namespace std;
using namespace std::filesystem;
auto main(int, char **) -> int {
// create absolute directory then symlink to it
create_directory("/tmp/tgt");
create_directory_symlink("/tmp/tgt", "/tmp/dir");
cout << "cwd0: " << current_path() << '\n';
current_path("/tmp/dir");
cout << "cwd1: " << current_path() << '\n';
remove("/tmp/tgt");
remove("/tmp/dir");
return 0;
}
Running this from within the /tmp
directory, the output is.
cwd0: "/tmp"
cwd1: "/tmp/tgt"
but what I want is for cwd1
to show /tmp/dir
Is there a portable mechanism to change the working directory to a symlink?
Your working directory has to be a directory. A symlink is not a directory. So no, this feature does not exist.
On the other hand, shells often emulate such behavior. For instance, in bash, if you do
cd /tmp
ln -s /some/other/dir foo
cd foo
cd ..
you end up back in /tmp
, not in /some/other
. The explanation is that cd ..
doesn't actually do chdir("..")
(which would put you in /some/other
for exactly the reason you stated). Instead, the shell uses an internal variable to keep track of the "logical" current directory, based on the sequence of previous cd
commands, and compute what the new working directory should be on that basis.
So if you want behavior like that, you'll have to emulate it yourself, just as shells do. It's not something the OS provides for you.