Change the current working directory in C++
Solution 1
The chdir
function works on both POSIX (manpage) and Windows (called _chdir
there but an alias chdir
exists).
Both implementations return zero on success and -1 on error. As you can see in the manpage, more distinguished errno values are possible in the POSIX variant, but that shouldn't really make a difference for most use cases.
Solution 2
Now, with C++17 is possible to use std::filesystem::current_path
:
#include <filesystem>
int main() {
auto path = std::filesystem::current_path(); //getting path
std::filesystem::current_path(path); //setting path
}
Solution 3
For C++, boost::filesystem::current_path (setter and getter prototypes).
A file system library based on Boost.Filesystem will be added to the standard.
Solution 4
This cross-platform sample code for changing the working directory using POSIX chdir
and MS _chdir
as recommend in this answer. Likewise for determining the current working directory, the analogous getcwd
and _getcwd
are used.
These platform differences are hidden behind the macros cd
and cwd
.
As per the documentation, chdir
's signature is int chdir(const char *path)
where path
is absolute or relative. chdir
will return 0 on success. getcwd
is slightly more complicated because it needs (in one variant) a buffer to store the fetched path in as seen in char *getcwd(char *buf, size_t size)
. It returns NULL on failure and a pointer to the same passed buffer on success. The code sample makes use of this returned char pointer directly.
The sample is based on @MarcD's but corrects a memory leak. Additionally, I strove for concision, no dependencies, and only basic failure/error checking as well as ensuring it works on multiple (common) platforms.
I tested it on OSX 10.11.6, Centos7, and Win10. For OSX & Centos, I used g++ changedir.cpp -o changedir
to build and ran as ./changedir <path>
.
On Win10, I built with cl.exe changedir.cpp /EHsc /nologo
.
MVP solution
$ cat changedir.cpp
#ifdef _WIN32
#include <direct.h>
// MSDN recommends against using getcwd & chdir names
#define cwd _getcwd
#define cd _chdir
#else
#include "unistd.h"
#define cwd getcwd
#define cd chdir
#endif
#include <iostream>
char buf[4096]; // never know how much is needed
int main(int argc , char** argv) {
if (argc > 1) {
std::cout << "CWD: " << cwd(buf, sizeof buf) << std::endl;
// Change working directory and test for success
if (0 == cd(argv[1])) {
std::cout << "CWD changed to: " << cwd(buf, sizeof buf) << std::endl;
}
} else {
std::cout << "No directory provided" << std::endl;
}
return 0;
}
OSX Listing:
$ g++ changedir.c -o changedir
$ ./changedir testing
CWD: /Users/Phil
CWD changed to: /Users/Phil/testing
Centos Listing:
$ g++ changedir.c -o changedir
$ ./changedir
No directory provided
$ ./changedir does_not_exist
CWD: /home/phil
$ ./changedir Music
CWD: /home/phil
CWD changed to: /home/phil/Music
$ ./changedir /
CWD: /home/phil
CWD changed to: /
Win10 Listing
cl.exe changedir.cpp /EHsc /nologo
changedir.cppc:\Users\Phil> changedir.exe test
CWD: c:\Users\Phil
CWD changed to: c:\Users\Phil\test
Note: OSX uses clang
and Centos gnu gcc
behind g++
.
Solution 5
Does chdir()
do what you want? It works under both POSIX and Windows.
sparkFinder
Updated on July 09, 2022Comments
-
sparkFinder almost 2 years
How can I change my current working directory in C++ in a platform-agnostic way?
I found the
direct.h
header file, which is Windows compatible, and theunistd.h
, which is UNIX/POSIX compatible.-
Jonathan Mee over 7 years@noɥʇʎPʎzɐɹC So the standard committee has established a standard required way to change the working directory, circa C++17, via
filesystem
. pepper_chico's answer already denotes that.filesystem
is currently available in g++5.3 and Visual Studio 2015 as an optional include. If that is the environment that you're working in I can write you an answer using#ifdef
to makefilesystem
's access cross platform? -
noɥʇʎԀʎzɐɹƆ over 7 years@JonathanMee if it is good enough, I may do a multiple bounty
-
-
sparkFinder almost 14 yearsI'm asking since Visual Studio wants me to use direct.h, but when I try building the same code in Linux, it crashes on my head, saying that I need to use unistd.h
-
rubber boots almost 14 yearsIn boost::filesystem, there wasn't a "chdir" when I used it last time.
-
RBerteig almost 14 years@sparkFinder, you will usually need to include different headers on different platforms when dealing with nonstandard functions such as
chdir()
. IIRC, GCC will define_WIN32
when targeting Windows, so you could use that with#include
to choose a header. -
Gilles 'SO- stop being evil' almost 14 years@rubber: indeed, looking at boost.org/doc/libs/1_34_1/boost/filesystem/operations.hpp suggests that there is a
getcwd
equivalent but nochdir
equivalent. -
AndiDog almost 14 years@sparkFinder: You can check for Visual Studio with
#ifdef _MSC_VER
and then include the direct.h header. If it's not defined, use unistd.h. This should be enough as the other major programming environment on Windows, MinGW, has the unistd header. -
R.. GitHub STOP HELPING ICE almost 14 yearsYou could just declare the prototype yourself.
-
noɥʇʎԀʎzɐɹƆ over 7 years
chdir
on windows is deprecated. -
noɥʇʎԀʎzɐɹƆ over 7 yearsGood example. But clean up and shorten your code and it will be yours.
-
MarcD over 7 years@ noɥʇʎPʎzɐɹC How's that? I shortened it a bit and cleaned it up. Can't shorten it much more.
-
noɥʇʎԀʎzɐɹƆ over 7 yearsCleaned it up a bit. I'll test it and put an example run for posix and then you'll get the bounty. :)
-
noɥʇʎԀʎzɐɹƆ over 7 yearsdid a mini code review: gist.github.com/CrazyPython/152805717b1c01649f0efed3415001e0 (it doesn't work on unix)
-
MarcD over 7 yearsIt works as expected. What do you want it to do? but doesn't escape it gets converted to a string
-
noɥʇʎԀʎzɐɹƆ over 7 yearsLet us continue this discussion in chat.
-
dbush over 7 years@noɥʇʎPʎzɐɹC Nothing about it being deprecated on this page. What's your source?
-
Jonathan Mee over 7 years@dbush
_chdir != chdir
_chdir
is not cross platform whilechdir
is deprecated. -
noɥʇʎԀʎzɐɹƆ over 7 yearsgive a clean and isolated one-liner for changing and viewing the current working directory.
-
noɥʇʎԀʎzɐɹƆ over 7 yearsand a function for those who want it, please
-
Nikita over 7 years@noɥʇʎPʎzɐɹC Added several helper functions to work both with
std::string
andboost::filesystem::path
. -
noɥʇʎԀʎzɐɹƆ over 7 yearswould you mind using
lowercase_with_underscores
, as this is the typical C++ convention? -
Nikita over 7 years@noɥʇʎPʎzɐɹC Not a problem, names updated to comply with
boost
naming and typical C++ code-style. -
noɥʇʎԀʎzɐɹƆ over 7 yearsI proposed an edit that shortens the names by a lot and changes
get_cwd
to a function that returns a string, most people will want the string. -
Nikita over 7 years@noɥʇʎPʎzɐɹC Thnx, changes accepted. I also shorten a variable names there.
-
noɥʇʎԀʎzɐɹƆ over 7 yearsooh, you put a lot of effort into this. You're leading on my list!
-
noɥʇʎԀʎzɐɹƆ over 7 yearsShorter than with libraries, and clean and neat. Provide a clear explanation of how to set and get the cwd, it's a bit vague right now.
-
siphr over 7 yearsThis answer is not correct as it promotes the use of a deprecated functionality as stated here msdn.microsoft.com/en-us/library/ms235420.aspx
-
Phil over 7 years@noɥʇʎPʎzɐɹC let me know if the update isn't clear to you.
-
Michael over 6 yearsI could see how one might think C and C++ were completely different languages if they were the only two languages you knew. or if C is the only language you knew
-
Gilles 'SO- stop being evil' over 6 years@Michael C and C++ have many characteristics in common: they're unsafe, imperative languages. They nonetheless are completely different languages, further apart than, say, C# and Java. It's true that C and C++ have a rather large common subset, but that common subset is almost never good C or good C++. If you think that C is a subset of C++, you're either a bad C programmer, or a bad C++ programmer, or both.
-
Dietrich Baumgarten about 4 yearsDoesn't work for me on Windows. What is the purpose of the condition argc > 1? Apps without parameters are allowed to have a working directory.
-
Phil almost 4 years@DietrichBaumgarten - are you seeing an error? The argc condition is to protect the indexing into argv in the demonstration program.
-
Dietrich Baumgarten almost 4 yearsNo Phil, everything ok, my mistake. I thought your solution required that the program has arguments, but you only used them for demonstration.
-
Marche Remi over 2 yearsThis changes only the current process's path. The operating shell's current path is not changed.
-
HiddenWindshield over 2 years@MarcheRemi Yes, that's typically what's meant when you want to change the current working directory. Under most OSs, it's not possible to change any other process' working directory at all.