I'm using fopen("aaa\bbb\ccc\myfile.txt","w")
to create output file. But folders aaa
, bbb
and ccc
don't exist. What is the best way to solve this problem? Is there are any standard way to ask fopen()
to create all needed folders?

- 3,929
- 1
- 23
- 30

- 17,051
- 45
- 159
- 315
-
9No, `fopen` will never make directories. There's a [question with good answers already](http://stackoverflow.com/questions/2336242/recursive-mkdir-system-call-on-unix/11425692) about an extended `mkdir()` that makes multiple levels, which is similar to what you want. You'd need to do that multi-level mkdir on `"aaa/bbb/ccc/"` then call `fopen`. – Jan 20 '14 at 14:35
-
2For windows you could use information in this post http://stackoverflow.com/questions/2834737/creating-new-folders-if-they-dont-exist-for-fopen – Alex Jones Jan 20 '14 at 16:12
-
3Remember to double those backslashes, in general that is. Won't help with the problem since `fopen()` simply doesn't support creating directories, but *if* the dirs existed it would be necessary. – unwind Jan 20 '14 at 16:17
-
@WumpusQ.Wumbley Why not answer instead of make a comment? So the author would be able to close this question. – Jérôme Pouiller Mar 23 '18 at 16:45
-
Folders are a GUI artefact. What the file system deals with is [directories](https://en.wikipedia.org/wiki/Directory_(computing)) and they are operating system specific. Standard C11 does not know about directories – Basile Starynkevitch May 27 '18 at 06:56
7 Answers
As others have noted, there is no cross-platform support for directories in the C standard library.
As far as my understanding goes, fopen()
and friends don't even know or care that the /
-es or \
-es in the path you give them are used as directory separators in the two major operating system families in use today.
For a cross-platform solution for single directory creation, see @dbush 's answer.
You can then wrap this with a function of your own that will take the complete file/directory path including all parent folders and create all the required parent folders (if needed), one-by-one.
For this, you will need to devise a way of extracting out each successive parent directory from your file path, starting from the top-most/left-most directory. Take care with splitting strings in C, as functions like strtok()
can be unsafe —you might be better off with a different approach for converting the path into a list of directories to create.
You may also need to handle cases where directories already exist, or where a file exists at a path where you wanted to place one of your directories.

- 779
- 1
- 6
- 22
Here is another alternative written in plain C, and that does not rely on strtok
(which mangles the passed file path string):
const char pathSeparator =
#ifdef _WIN32
'\\';
#else
'/';
#endif
// Given a file path, create all constituent directories if missing
void create_file_path_dirs(char *file_path) {
char *dir_path = (char *) malloc(strlen(file_path) + 1);
char *next_sep = strchr(file_path, pathSeparator);
while (next_sep != NULL) {
int dir_path_len = next_sep - file_path;
memcpy(dir_path, file_path, dir_path_len);
dir_path[dir_path_len] = '\0';
mkdir(dir_path, S_IRWXU|S_IRWXG|S_IROTH);
next_sep = strchr(next_sep + 1, pathSeparator);
}
free(dir_path);
}

- 683
- 5
- 16
If you can mix some C++ in your program, boost.filesystem library has a very handy function to create all intermediate directories.
bool create_directories(const path& p);

- 5,438
- 2
- 27
- 32
The C Std. Lib. functions for opening and writing-to files, while they can create new files in existing directories, they cannot create new directories. To do that, I suggest using the "mkdir" function from header "sys/stat.h" and the "chdir" function from header "unistd.h".
For example, if writing a C program to be used on Cygwin on Windows 10, something like this would work:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#include <error.h>
int main (void)
{
FILE * fp;
chdir("/cygdrive/d");
if (mkdir("aaa", S_IRWXU|S_IRWXG|S_IROTH))
{
error(EXIT_FAILURE, errno, "Failed to create directory aaa");
}
chdir("aaa");
if (mkdir("bbb", S_IRWXU|S_IRWXG|S_IROTH))
{
error(EXIT_FAILURE, errno, "Failed to create directory bbb");
}
chdir("bbb");
if (mkdir("ccc", S_IRWXU|S_IRWXG|S_IROTH))
{
error(EXIT_FAILURE, errno, "Failed to create directory ccc");
}
chdir("ccc");
fp=fopen("MyFile.txt", "w");
if (!fp)
{
error(EXIT_FAILURE, errno, "Failed to open file for writing");
}
fprintf(fp, "Test.\n");
fclose(fp);
return 0;
}
That will create the directory "D:\aaa\bbb\ccc", then create a file in that directory called "MyFile.txt", then write "Test.\n" to that file.

- 109
- 8
Probably not as elegant as other ones but:
system("mkdir aaa\\bbb\\ccc\\");
FILE * fp;
fp = fopen("aaa/bbb/ccc/myfile.txt","w");
For linux use -p
option and slashes.
backslashes should be in system()
function if you're using Windows
-
-
The backslashes should be escaped, and could be replaced by slashes. – Basile Starynkevitch May 27 '18 at 07:00
-
Forgot about that, thanks. If the user uses Windows, then terminal will return syntax error (and not creating the directory) if using slashes – C Chorche May 28 '18 at 07:52
if you are using fopen()
then you should create the parent directories first.
you can simply do this by
system("mkdir -p aaa/bbb/ccc");
fopen("aaa/bbb/ccc/myfile.txt","w");
don't forget to include header file <stdlib.h>
in this program

- 564
- 2
- 21
-
The backslashes should be escaped, and could be replaced by slashes. The `mkdir` command might not exist or not know about `-p` – Basile Starynkevitch May 27 '18 at 06:57
fopen() is used to open input streams for text or binary files and not the directory files. If you want to have your file open in a path which holds non-existant directories, I'd suggest you use the mkdir() method of the /sys/stat.h header file. Once you have the directories ready you can used fopen() to open the file you need(or create it if not already present). This is the approach that I used to create a file in the a directory of my $HOME folder:-
char* home_dir= getenv("HOME");
/*creates the directory with specified modes*/
mkdir(strcat(home_dir, "/make-a-note/"),S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
/*used the strcat() to generate the file-path.*/
personal_work=fopen(strcat(home_dir,"personal_work.txt"),"a+");

- 25
- 5
-
1Don't use that code, the `strcat()` call is evil: It definitely overruns the buffer holding the environment variables content. This undefined behavior will likely trash some other environment variable(s), or worse. – cmaster - reinstate monica Mar 14 '17 at 17:12