Question

I have such string (it's a string that represents a system path actually):

./home/user/dir1/dir2/

And now, I would like to be able to create presented directory tree, so I need to create home, user, dir1, dir2.

I know how to create dirs in C in Linux, but have troubles with chopping off the string. Basically, what I need now is to have an array of strings:

tmp[0] = "./home/";
tmp[1] = "./home/user/";
tmp[2] = "./home/user/dir1/";
tmp[3] = "./home/user/dir1/dir2/";

and if I will hav such array it would be pretty easy to make presented dir tree but how to split the string in that way?

Was it helpful?

Solution

This is a bit naive but it should get you started. It will handle paths that may or may not have a trailing / and also escaped paths, such as ./home/some\/user/dir1/dir2

#include <stdio.h>                                                                                                                  
#include <string.h>

int main(int argc, char *argv[])
{
    char path[] = "./home/user/dir1/dir2";
    char *start = path;
    char *end = start + strlen(path);

    while (start < end) {
        char *slash = strchr(start, '/');

        if (slash) {
            if (slash > path && *(slash - 1) == '\\') {
                start = slash + 1;
                continue;
            }

            *slash = 0;
        }

        if (strcmp(start, ".") != 0) {
            /* Use 'path' for mkdir here */
            /* mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) or whatever */
            printf("going to make %s\n", path);
        }

        if (!slash) {
            break;
        }

        *slash = '/';
        start = slash + 1;
    }

    return 0;
}

OTHER TIPS

I'd go for Sean's advice as "You should just exec() mkdir -p ... and save yourself the headache."

However if C is necessary, there you go:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define BUF_SIZE 100

int main(){
    char s[] = "./home/user/dir1/dir2/";
    char** tmp;
    int i, j;
    int size = 0;
    char* token;

    /* count the '/' characters */
    char c = s[0];
    int count = 0;
    i = 0;
    while (c != '\0'){
        if (s[i] == '/')
            count++;

        i++;
        c = s[i];
    }

    size = i;

    /* ready the tmp array */
    tmp = (char**)malloc(count);
    for (i = 0; i < count; i++){
        tmp[i] = (char*)malloc(BUF_SIZE);
        for (j = 0; j < BUF_SIZE; ++j)
            tmp[i][j] = '\0';
    }

    /* special treatment for our first tmp[] */
    tmp[0][0] = '.';
    tmp[0][1] = '/';


    i = 0;
    /* tokenize the main string */
    token = strtok(s, "./");
    while (token != NULL){

        if (i > 0)
            strcat(tmp[i], tmp[i - 1]);

        strcat(tmp[i], token);
        strcat(tmp[i], "/");
        printf("%s\n", tmp[i]);

        token = strtok(NULL, "/");
        i++;
    }

    /* clean up */
    for (i = 0; i < count; i++)
        free(tmp[i]);

    getchar();
    return 0;
}

The output is:

./home/
./home/user/
./home/user/dir1/
./home/user/dir1/dir2/

I would use strtok to parse the directory names from the string using "/" as the delimiter.

see: http://www.cplusplus.com/reference/cstring/strtok/

Heres how I did it:

#include <stdio.h>
#include <string.h>

// Count the number of times the character appears in the string
size_t countInstances(char* str, char token) {
    size_t count = 0;
    while(*str) {
        if(*str == token) {
            count++;
        }
        str++;
    }

    return count;
}

int main() {
    char path[] = "./home/user/dir1/dir2/"; // strtok might segfault if this is a pointer (rather than an array)

    size_t count = countInstances(path, '/');
    char** dirs = malloc(sizeof(*dirs) * count);
    char* dir;
    size_t i = 0;

    dir = strtok(path, "/");
    while(dir && i < count) {
        dirs[i] = dir; // store reference

        printf("%s\n",dir);
        dir = strtok (NULL, "/");
        i++;
    }

    free(dirs);
    return 0;
}

output is:

.
home
user
dir1
dir2
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top