文件和目录之函数mkdir、mkdirat、rmdir和读目录函数

mkdirmkdirat函数来创建目录,用rmdir函数删除目录。

#include <sys/stat.h>
int mkdir(const char *pathname, mode_t mode);
int mkdirat(int fd, const char *pathname, mode_t mode);
两个函数返回值:若成功,返回 0;若失败,返回 -1

mkdirmkdirat函数在fd指定为AT_FDCWDpathname参数指定为绝对路径名时两者是完全一样的。否则,fd参数是一个打开目录,相对路径名根据此打开目录进行计算。

测试示例

void test1(){                                                                   
     if(mkdir("mkdirfile", 0775) < 0)                                            
         err_sys("mkdir error.");                                                
     printf("mkdir success.\n");
}   
void test2(){                                                                   
     if(mkdirat(AT_FDCWD, "mkdiratfile", 0775) < 0)                              
         err_sys("mkdirat error.");                                              
     int fd;                                                                     
     printf("mkdirat success.\n");                                               
     if((fd=open("../exercise", O_RDONLY)) < 0)                                  
         err_sys("open error.");                                                 
     if(mkdirat(fd, "mkdiratfile2", 0755) < 0)                                   
         err_sys("mkdirat error.");                                                                                          
     printf("mkdirat success.\n");                                               
     close(fd);
}       

结果如下:

通过上图可知,在当前目录下mkdir创建了mkdirfile目录,当mkdirat函数fd参数指定为AT_FDCWD时,与mkdir函数完全一样,mkdiratfile则是在当前目录下由mkdirat函数创建的目录;当fd参数指定为../exercise(即为打开一个目录)时,则相对路径名依此进行计算并在创建了../exercise下创建了mkdiratfile2。

 

rmdir函数可以删除一个空目录,空目录即为只包含...的目录。

#include <unistd.h>
int rmdir(const char *pathname);
函数返回值: 若成功,返回 0; 若出错,返回 -1。

测试示例:

void test3(){                                                                   
     if(rmdir("mkdirfile") < 0)                                                  
         err_sys("rmdir error.");                                                
     printf("rmdir success.\n");
}    

结果如下:

由图可知mkdirfile目录被删除。

 

对某个目录具有访问权限的任一用户都可以读该目录,但是为了防止文件系统产生混乱,只有内核才能写目录。

#include <dirent.h>
DIR *opendir(const char *pathname);
DIR *fdopendir(int fd);
两个函数返回值:若成功,返回 0;若出错,返回NULL。
struct dirent *readdir(DIR *dp);
返回值:若成功,返回 0;若在目录尾或出错,返回NULL。
void rewinddir(DIR *dp);
int closedir(DIR *dp);
返回值:若成功,返回 0;若出错,返回 -1。
long telldir(DIR *dp);
返回值:与dp关联的目录中的当前位置
void seekdir(DIR *dp, long loc);

dirent结构体定义在头文件<dirent.h>中,具体结构与实现有关。实现对此结构所做的定义至少包含以下两个成员:

ino_t d_ino; // i-node number
char d_name[256]; // null-terminated filename

该结构体在glibc中的具体实现如下:

struct dirent{
   ino_t d_ino; // inode number
   off_t d_off; // not an offset
   unsigned short d_reclen; // Length of this record
   unsigned char d_type; /* type of file, not supported by all filesystem types */
   char d_name[256]; // null-terminated filename
};

小试牛刀,我们来使用上述目录操作编写一个简单的统计目录下个文件个数的程序如下:

#include "../../include/apue.h"
#include <dirent.h>
#include <limits.h>
/*
 * function type that is called for each filename
 * */
typedef int Myfunc(const char *, const struct stat *, int);

static Myfunc myfunc;
static int myftw(char *, Myfunc *);
static int dopath(Myfunc *);
static long nreg, nblk, ndir, nchr, nfifo, nslink, nsock, ntot; 

int main(int argc, char *argv[])
{
    int ret;
    if(argc != 2)
        err_quit("usage: ftw <starting-pathname>");
    ret = myftw(argv[1], myfunc);
    ntot = nreg + ndir + nblk + nchr + nfifo + nslink + nsock;
    if(ntot == 0)
        ntot = 1;
    printf("total          = %7ld\n", ntot);
    printf("regular files  = %7ld, %5.2f %%\n", nreg, nreg*100.0/ntot);
    printf("directories    = %7ld, %5.2f %%\n", ndir, ndir*100.0/ntot);
    printf("block special  = %7ld, %5.2f %%\n", nblk, nblk*100.0/ntot);
    printf("char special   = %7ld, %5.2f %%\n", nchr, nchr*100.0/ntot);
    printf("FIFOs          = %7ld, %5.2f %%\n", nfifo, nfifo*100.0/ntot);
    printf("symbolic links = %7ld, %5.2f %%\n", nslink, nslink*100.0/ntot);
    printf("sockets        = %7ld, %5.2f %%\n", nsock, nsock*100.0/ntot);
    return 0;
}
/*
 * Descend through the hierarchy, starting at "pathname".
 * The caller's func() is called for every file.
 * */
#define FTW_F 1
#define FTW_D 2
#define FTW_DNR 3
#define FTW_NS 4

static char *fullpath;
static size_t pathlen;

static int myftw(char *pathname, Myfunc *func)
{
    fullpath = path_alloc(&pathlen);

    if(pathlen <= strlen(pathname)){
        pathlen = strlen(pathname) * 2;
        if((fullpath = (char *)realloc(fullpath, pathlen)) == NULL)
            err_sys("realloc failed");
    }
    strcpy(fullpath, pathname);
    return (dopath(func));
}
/*
 * Descend through the hierachy, starting at "fullpath".
 * If "fullpath" is anything other than a directory , we lstat() it,
 * call func() , and return. For a directory , we call ourself
 * recursively for each name in the directory.
 * */

static int dopath(Myfunc *func)
{
    struct stat statbuf;
    struct dirent *dirp;
    DIR *dp;
    int ret, n;
    if(lstat(fullpath, &statbuf) < 0)
        return (func(fullpath, &statbuf, FTW_NS));
    if(S_ISDIR(statbuf.st_mode) == 0)
        return (func(fullpath, &statbuf, FTW_F));
    /*
     * It's a directory. First call func() for the directory, 
     * then process each filename in the directory.
     * */
    if((ret = func(fullpath, &statbuf, FTW_D)) != 0)
        return (ret);
    n = strlen(fullpath);
    if(n + NAME_MAX + 2 > (int)pathlen){
        pathlen *= 2;
        n = strlen(fullpath);
        if((fullpath = (char *)realloc(fullpath, pathlen)) == NULL)
            err_sys("realloc failed");
    }
    fullpath[n++] = '/';
    fullpath[n] = 0;
    if((dp = opendir(fullpath)) == NULL)
        return (func(fullpath, &statbuf, FTW_DNR));
    while((dirp = readdir(dp)) != NULL){
        if(strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0)
            continue;
        strcpy(&fullpath[n], dirp->d_name);
        if((ret = dopath(func)) != 0)
            break;
    }
    fullpath[n-1] = 0;
    if(closedir(dp) < 0)
        err_ret("can't close directory %s", fullpath);
    return (ret);
}
static int myfunc(const char *pathname, const struct stat *statptr, int type)
{
    switch(type){
    case FTW_F:
        switch(statptr->st_mode & S_IFMT){
            case S_IFREG: nreg++; break;
            case S_IFBLK: nblk++; break;
            case S_IFCHR: nchr++; break;
            case S_IFIFO: nfifo++; break;
            case S_IFLNK: nslink++; break;
            case S_IFSOCK: nsock++; break;
            case S_IFDIR: 
                err_dump("for S_IFDIR for %s", pathname);
        }
        break;
    case FTW_D:
        ndir++; break;
    case FTW_DNR:
        err_ret("can't read directory %s", pathname);
        break;
    case FTW_NS:
        err_ret("stat error for %s", pathname);
        break;
    default:
        err_dump("unknown type %d for pathname %s", type, pathname);
    }
    return (0);
}

#ifdef PATH_MAX
static long pathmax = PATH_MAX;
#else
static long pathmax = 0;
#endif

static long posix_version = 0;
static long xsi_version = 0;

/* If PATH_MAX is indeterminate,  no guarantee this is adequate*/
#define PATH_MAX_GUESS 1024
char * path_alloc(size_t *sizep)
{
    char *ptr;
    size_t size;
    if(posix_version == 0){
        posix_version = sysconf(_SC_VERSION);
    }
    if(xsi_version == 0){
        xsi_version = sysconf(_SC_XOPEN_VERSION);
    }
    if(pathmax == 0){
        errno = 0;
        if((pathmax = pathconf("/", _PC_PATH_MAX)) < 0){
            if(errno == 0)
                pathmax = PATH_MAX_GUESS;
            else
                err_sys("pathconf error for _PC_PATH_MAX");
        }else{
            pathmax++;
        }
    }
    /*
     * Before POSIX.1 - 2001, we aren't guaranteed that PATH_MAX includes
     * the terminating null byte. Same goes for XPG3.
     * */
    if((posix_version < 20011L) && (xsi_version < 4))
        size = pathmax + 1;
    else
        size = pathmax;
    if((ptr = (char *)malloc(size)) == NULL)
        err_sys("malloc error for pathname");

    if(sizep != NULL)
        *sizep = size;
    return (ptr);
}

结果如下:

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Qt中,可以使用QFile和QDir类来实现文件目录的改变。QFile类提供了一组用于操作文件函数,可以创建、打开、取、写入和关闭文件等操作。QDir类提供了一组用于操作目录函数,可以创建、删除、重命名、遍历目录等操作。以下是一个示例代码: ```cpp #include <QCoreApplication> #include <QDebug> #include <QFile> #include <QDir> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QString filePath = "C:/Users/abc/Desktop/test.txt"; QString dirPath = "C:/Users/abc/Desktop/testdir"; // 创建文件 QFile file(filePath); if(file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream out(&file); out << "Hello, world!"; file.close(); qDebug() << "Create file successfully."; } else { qDebug() << "Create file failed."; } // 创建目录 QDir dir; if(dir.mkdir(dirPath)) { qDebug() << "Create directory successfully."; } else { qDebug() << "Create directory failed."; } // 重命名文件 QString newFilePath = "C:/Users/abc/Desktop/newtest.txt"; if(file.rename(newFilePath)) { qDebug() << "Rename file successfully."; } else { qDebug() << "Rename file failed."; } // 删除目录 if(dir.rmdir(dirPath)) { qDebug() << "Remove directory successfully."; } else { qDebug() << "Remove directory failed."; } return a.exec(); } ``` 在上面的示例代码中,我们首先定义了一个文件路径和一个目录路径。然后,我们使用QFile类创建了一个文件,并使用QTextStream类向文件中写入了一些文本。接着,我们使用QDir类创建了一个目录。然后,我们使用QFile类的rename函数文件重命名为新的文件名。最后,我们使用QDir类的rmdir函数删除了目录。 注意:在进行文件目录的改变时,需要先判断操作是否成功,可以通过QFile和QDir类提供的返回值来判断。另外,在重命名文件时,需要使用QFile类的rename函数,而不能直接使用QFile类的renameTo函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值