Car*_*rum 86
不幸的是,没有系统调用来为你做这件事.我猜这是因为没有办法为错误情况下应该发生的事情提供真正明确定义的语义.它应该离开已经创建的目录吗?删除它们?如果删除失败怎么办?等等...
然而,滚动你自己很容易,快速谷歌的' 递归mkdir '提出了许多解决方案.这是一个接近顶部的:
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);
}
Run Code Online (Sandbox Code Playgroud)
j03*_*03m 66
嗯,我以为mkdir -p会那么做?
mkdir -p this /是/ a/full/path/of/stuff
Yar*_*hiy 23
这是我的解决方案.通过调用下面的函数,您可以确保存在指向文件路径的所有dirs.请注意,file_path
参数不是此处的目录名,而是调用后要创建的文件的路径mkpath()
.
例如,如果不存在mkpath("/home/me/dir/subdir/file.dat", 0755)
则应创建/home/me/dir/subdir
.mkpath("/home/me/dir/subdir/", 0755)
做同样的事.
也适用于相对路径.
发生错误时返回-1
并设置errno
.
int mkpath(char* file_path, mode_t mode) {
assert(file_path && *file_path);
for (char* 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;
}
Run Code Online (Sandbox Code Playgroud)
请注意,file_path
在操作期间会对其进行修改,但之后会进行恢复.因此file_path
并不严格const
.
tro*_*bit 11
这是另一种mkpath()
使用递归的方法,它既小又可读.它strdupa()
用于避免dir
直接改变给定的字符串参数并避免使用malloc()
&free()
.确保编译-D_GNU_SOURCE
以激活strdupa()
...意味着此代码仅适用于GLIBC,EGLIBC,uClibc和其他GLIBC兼容的C库.
int mkpath(char *dir, mode_t mode)
{
if (!dir) {
errno = EINVAL;
return 1;
}
if (strlen(dir) == 1 && dir[0] == '/')
return 0;
mkpath(dirname(strdupa(dir)), mode);
return mkdir(dir, mode);
}
Run Code Online (Sandbox Code Playgroud)
在这里和Valery Frolov输入之后,在Inadyn项目中,以下修订版本mkpath()
现已被推到libite
int mkpath(char *dir, mode_t mode)
{
struct stat sb;
if (!dir) {
errno = EINVAL;
return 1;
}
if (!stat(dir, &sb))
return 0;
mkpath(dirname(strdupa(dir)), mode);
return mkdir(dir, mode);
}
Run Code Online (Sandbox Code Playgroud)
它再使用一个系统调用,但是现在代码更易读.
看一下这里的bash源代码,具体看看examples/loadables/mkdir.c,特别是136-210行.如果你不想这样做,这里有一些处理这个问题的来源(直接来自我链接的tar.gz):
/* 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;
}
Run Code Online (Sandbox Code Playgroud)
您可以通过不太常规的实现来逃避.
显然不是,我的两个建议是:
char dirpath[80] = "/path/to/some/directory";
sprintf(mkcmd, "mkdir -p %s", dirpath);
system(mkcmd);
Run Code Online (Sandbox Code Playgroud)
或者,如果您不想使用system()
try查看coreutils mkdir
源代码并查看它们如何实现该-p
选项.
归档时间: |
|
查看次数: |
90357 次 |
最近记录: |