Après la lecture de la mkdir(2) page de man pour le système Unix appel avec ce nom, il semble que l'appel n'est pas de créer des répertoires intermédiaires dans un chemin d'accès, seul le dernier répertoire dans le path. Est-il possible (ou d'autres) pour créer tous les répertoires dans le chemin sans avoir recours à l'manuellement l'analyse de mon répertoire de chaîne et individuellement de la création de chaque répertoire ?
Réponses
Trop de publicités?Il n'est pas un appel système pour le faire pour vous, malheureusement. Je suppose que c'est parce qu'il n'y a pas un moyen d'avoir vraiment sémantique bien définie pour ce qui devrait se produire en cas d'erreur. Faut-il laisser les répertoires qui ont déjà été créés? Les supprimer? Que faire si les suppressions d'échouer? Et ainsi de suite...
Il est assez facile de rouler votre propre, cependant, et un rapide google pour"récursive mkdir' mis en place un certain nombre de solutions. Voici un qui était près du sommet:
http://nion.modprobe.de/blog/archives/357-Recursive-directory-creation.html
static void _mkdir(const char *dir) {
char tmp[256];
char *p = NULL;
size_t len;
snprintf(tmp, sizeof(tmp),"%s",dir);
len = strlen(tmp);
if(tmp[len - 1] == '/')
tmp[len - 1] = 0;
for(p = tmp + 1; *p; p++)
if(*p == '/') {
*p = 0;
mkdir(tmp, S_IRWXU);
*p = '/';
}
mkdir(tmp, S_IRWXU);
}
Voici ma solution. En appelant la fonction ci-dessous vous assurer que tous les dirs menant au chemin d'accès au fichier spécifié existe. Notez que file_path
argument n'est pas de répertoire nom ici, mais plutôt un chemin vers un fichier que vous allez créer après l'appel de mkpath()
.
Eg., mkpath("/home/me/dir/subdir/file.dat", 0755)
créer /home/me/dir/subdir
si elle n'existe pas. mkpath("/home/me/dir/subdir/", 0755)
fait de même.
Fonctionne avec des chemins relatifs, ainsi.
Les retours -1
et définit errno
dans le cas d'une erreur.
int mkpath(char* file_path, mode_t mode) {
assert(file_path && *file_path);
char* p;
for (p=strchr(file_path+1, '/'); p; p=strchr(p+1, '/')) {
*p='\0';
if (mkdir(file_path, mode)==-1) {
if (errno!=EEXIST) { *p='/'; return -1; }
}
*p='/';
}
return 0;
}
Notez que file_path
est modifié au cours de l'action, mais est restauré par la suite. Par conséquent, file_path
n'est pas strictement const
.
Jetez un oeil à la source de bash code ici, et en particulier dans les exemples/loadables/mkdir.c surtout les lignes 136-210. Si vous ne voulez pas le faire, voici une partie de la source qui traite de ce (pris directement à partir de la tar.gz que j'ai mis en lien):
/* Make all the directories leading up to PATH, then create PATH. Note that
this changes the process's umask; make sure that all paths leading to a
return reset it to ORIGINAL_UMASK */
static int
make_path (path, nmode, parent_mode)
char *path;
int nmode, parent_mode;
{
int oumask;
struct stat sb;
char *p, *npath;
if (stat (path, &sb) == 0)
{
if (S_ISDIR (sb.st_mode) == 0)
{
builtin_error ("`%s': file exists but is not a directory", path);
return 1;
}
if (chmod (path, nmode))
{
builtin_error ("%s: %s", path, strerror (errno));
return 1;
}
return 0;
}
oumask = umask (0);
npath = savestring (path); /* So we can write to it. */
/* Check whether or not we need to do anything with intermediate dirs. */
/* Skip leading slashes. */
p = npath;
while (*p == '/')
p++;
while (p = strchr (p, '/'))
{
*p = '\0';
if (stat (npath, &sb) != 0)
{
if (mkdir (npath, parent_mode))
{
builtin_error ("cannot create directory `%s': %s", npath, strerror (errno));
umask (original_umask);
free (npath);
return 1;
}
}
else if (S_ISDIR (sb.st_mode) == 0)
{
builtin_error ("`%s': file exists but is not a directory", npath);
umask (original_umask);
free (npath);
return 1;
}
*p++ = '/'; /* restore slash */
while (*p == '/')
p++;
}
/* Create the final directory component. */
if (stat (npath, &sb) && mkdir (npath, nmode))
{
builtin_error ("cannot create directory `%s': %s", npath, strerror (errno));
umask (original_umask);
free (npath);
return 1;
}
umask (original_umask);
free (npath);
return 0;
}
Vous pouvez probablement vous en sortir avec moins de mise en œuvre.