linux下文件、目录操作

文件的打开

/*
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    // 打开一个已经存在的文件
    int open(const char *pathname, int flags);
        参数:
            - pathname:要打开的文件路径
            - flags:对文件操作的权限设置还有其他的设置
                O_RDONLY, O_WRONLY, O_RDWR // 这三个设置是互斥的
        返回值:
            - 返回一个新的文件描述符,如果调用失败,返回-1
    // errno:属于Linux系统函数库,库里边的全局变量,记录最近的错误号。

    // 打印errno对应的错误描述
    #include <stdio.h>
    void perror(const char *s);
    // s参数:用户描述,比如"hello",实际输出的内容是 hello:xxx(实际的错误描述)
    
    // 关闭文件
    #include <unistd.h>
    int close(int fd);
    
    // 创建一个新的文件
    int open(const char *pathname, int flags, mode_t mode);
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

#include <iostream>
int main(){
    int fd = open("./a.txt", O_RDONLY);
    std::cout << fd << std::endl;
    if (fd == -1) {
        perror("open");
    }
    // 关闭
    close(fd);
    return 0;
}

文件的创建

/*
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>

    int open(const char *pathname, int flags, mode_t mode);
        参数:
            - pathname:创建的文件路径
            - flags:对文件的操作权限和其他设置
                - 必选项 O_RDONLY, O_WRONLY, O_RDWR 互斥
                - 可选项 O_CREAT 文件不存在,创建新文件
            - mode:八进制的数,表示用户对创建出的新的文件的操作权限,比如0775
            最终的权限是:mode & ~umask
            umash:0002 -> 二进制0 000 000 010 ~0002 -> 0775 -> 二进制 0 111 111 101
            0777 -> 二进制 0 111 111 111
            ~0002-> 二进制 0 111 111 101
                        &  
                           0 111 111 101
            umask的作用是抹去某些权限,让我们创建的文件或者目录的权限合理

            flags参数占4个字节,32位
            flags 32位,每一位都是标志位,代表一种情况
*/

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(){
    int fd = open("./creat.txt", O_RDWR | O_CREAT, 0666);

    if (fd == -1) {
        perror("open");
    }
    close(fd);
    return 0;
}

文件的读写

/*
    #include <unistd.h>
    
    ssize_t read(int fd, void *buf, size_t count);
        参数:
            - fd:文件描述符,open得到的,通过文件描述符操作文件
            - buf:缓冲区。需要读取数据存放的的地方。
            - count:指定的数组的大小
        返回值:
            - 成功:
                >0:返回实际读取到的字节数
                =0:文件已经读取完了
            - 失败:-1,并且设置errno

    #include <unistd.h>

    ssize_t write(int fd, const void *buf, size_t count);
        参数:
            - fd:文件描述符
            - buf:往磁盘写入的数据。数组
            - coutn:要写的数据的实际大小
        返回值:
            - 成功:实际写入的字节数
            - 失败:返回-1,并设置errno

*/


#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


int main(){
    // 通过open打开english.txt文件
    int srcfd = open("./english.txt", O_RDONLY);
    if (srcfd == -1) {
        perror("open");
        return -1;
    }

    // 创建新的文件
    int destfd = open("./english_copy.txt", O_WRONLY | O_CREAT, 0664);
    if (destfd == -1) {
        perror("open");
        return -1;
    }

    // 频繁的读写操作
    char buf[1024] = {0};
    int len = 0;
    while ((len = read(srcfd, buf, sizeof(buf))) > 0)
    {
        int l = write(destfd, buf, len);
    }
    
    // 关闭文件
    close(destfd);
    close(srcfd);

    return 0;
}

文件偏移量的重新定位

/*
    标准C库函数
    #include <stdio.h>
    int fseek(FILE *stream, long offset, int whence);

    linux系统函数
    #include <sys/types.h>
    #include <unistd.h>
    off_t lseek(int fd, off_t offset, int whence);
        参数:
            - offset:偏移量
            - whence:
                SEEK_SET:设置文件指针的偏移量
                SEEK_CUR:设置偏移量,当前位置+第二个参数offset值
                SEEK_END:设置偏移量,文件大小+第二个参数offset值
        返回值:返回文件指针最终的位置
        作用:
            1、移动指针到文件开头
                lseek(fd, 0, SEEK_SET);
            2、获取当前指针的位置
                lseek(fd, 0, SEEK_CUR);
            3、获取文件长度
                lseek(fd, 0, SEEK_END);
            4、拓展文件长度,当前文件10b,拓展到110b
                lseek(fd, 100, SEEK_END);
                // 需要写入一次数据
*/

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main(){

    int fd = open("./hello.txt", O_RDWR);
    if (fd == -1) {
        perror("open");
        return -1;
    }

    // 拓展文件长度
    int ret = lseek(fd, 100, SEEK_END);
    if (ret == -1) {
        perror("lseek");
        return -1;
    }
    // 写入空数据
    write(fd, " ", 1);

    // 关闭文件
    close(fd);

    return 0;
}


文件权限查询

/*
    #include <unistd.h>
    int access(const char *pathname, int mode);
        作用:判断当前进程对文件是否有某个权限 文件是否存在
        参数:
            - pathname:判断的文件路径
            - mode:
                R_OK 是否有读权限
                W_OK 是否有写权限
                X_OK 是否有执行权限
                F_OK 是否存在
        返回值:成功返回0,失败返回-1
*/

#include <unistd.h>
#include <stdio.h>
int main(){
    int ret = access("./a.txt", W_OK);
    if (ret == -1) {
        perror("access");
    }
    printf("文件可写!\n");
    return 0;
}

文件权限修改

/*
    #include <sys/stat.h>   
    int chmod(const char *pathname, mode_t mode);
        参数:
            - pathname:文件路径
            - mode:需要修改的全限值,八进制数
        返回值:成功返回0,失败返回-1
*/

#include <sys/stat.h>
#include <stdio.h>
int main(){
    int ret = chmod("./a.txt", 0775);
    if (ret == -1) {
        perror("access");
        return -1;
    }
    return 0;
}

文件尺寸修改

/*
    #include <unistd.h>
    #include <sys/types.h>   
    int truncate(const char *path, off_t length);
        作用:缩减或扩展文件的尺寸至指定大小
        参数:
            - path:文件路径
            - length:需要文件最终变成的大小
        返回值:成功返回0,失败返回-1
*/
#include <unistd.h>
#include <sys/types.h>  
#include <stdio.h>
int main(){
    int ret = truncate("./b.txt", 5);
    if (ret == -1) {
        perror("access");
    }
    return 0;
}

文件信息获取

/*
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>

    int stat(const char *pathname, struct stat *statbuf);
        作用:获取文件相关的信息
        参数:
            - pathname:文件路径
            - statbuf:结构体变量指针,传出参数,用于保存获取到的文件信息
        返回值:成功则返回0,失败则返回-1,并设置errno




    int lstat(const char *pathname, struct stat *statbuf);
        
        参数:
            - pathname:文件路径
            - statbuf:结构体变量指针,传出参数,用于保存获取到的文件信息
        返回值:成功则返回0,失败则返回-1,并设置errno

*/

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>


int main(){
    struct stat statbuf;
    
    int ret = stat("a.txt", &statbuf);
    if (ret == -1) {
        perror("stat");
        return -1;
    }

    printf("size:%ld\n", statbuf.st_size);


    return 0;
}

笔记

模拟ls -l指令

// 模拟实现ls -l指令
// -rw-rw-r-- 1 carrot carrot 13 4月   4 15:45 a.txt
#include <iostream>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include <pwd.h>
#include <grp.h>

#include <time.h>

#include <string.h>

int main(int argc, char* argv[]){
    if (argc < 2) {
        std::cout << argv[0] << " filename" << std::endl;
        return -1;
    }
    
    struct stat statbuf;
    int ret = stat(argv[1], &statbuf);
    if (ret == -1) {
        perror("stat");
        return -1;
    }

    // 获取文件类型和文件权限
    char perms[11] = {0}; // 用于保存文件类型和文件权限的字符串

    switch (statbuf.st_mode & S_IFMT)
    {
    case S_IFLNK:
        perms[0] = 'l';
        break;
    case S_IFDIR: // 目录
        perms[0] = 'd';
        break;
    case S_IFREG: // 普通文件
        perms[0] = '-';
        break;
    case S_IFBLK: // 块文件
        perms[0] = 'b'; 
        break;
    case S_IFCHR: // 字符设备
        perms[0] = 'c';
        break;
    case S_IFSOCK: // 套接字
        perms[0] = 'S';
        break;
    case S_IFIFO: // 管道
        perms[0] = 'p';
        break;

    default:
        perms[0] = '?';
        break;
    }
    
    // 文件所有者
    perms[1] = (statbuf.st_mode & S_IRUSR ? 'r' : '-');
    perms[2] = (statbuf.st_mode & S_IWUSR ? 'w' : '-');
    perms[3] = (statbuf.st_mode & S_IXUSR ? 'x' : '-');

    // 文件所在组
    perms[4] = (statbuf.st_mode & S_IRGRP ? 'r' : '-');
    perms[5] = (statbuf.st_mode & S_IWGRP ? 'w' : '-');
    perms[6] = (statbuf.st_mode & S_IXGRP ? 'x' : '-');

    perms[7] = (statbuf.st_mode & S_IROTH ? 'r' : '-');
    perms[8] = (statbuf.st_mode & S_IWOTH ? 'w' : '-');
    perms[9] = (statbuf.st_mode & S_IXOTH ? 'x' : '-');

    // 获取硬链接数
    int linkNum = statbuf.st_nlink;

    // 文件所有者
    char *fileUser = getpwuid(statbuf.st_uid)->pw_name;

    // 文件所在组
    char *fileGrp = getgrgid(statbuf.st_gid)->gr_name;

    // 文件大小
    long int filesize = statbuf.st_size;

    // 获取修改时间
    char *time = ctime(&statbuf.st_mtim.tv_sec); // 最后带一个回车
    char mtime[512] = {0};
    strncpy(mtime, time, strlen(time) - 1);


    char buf[1024] = {0};
    sprintf(buf, "%s %d %s %s %ld %s %s", perms, linkNum, fileUser, fileGrp, filesize, mtime, argv[1]);
    std::cout << buf <<std::endl;

    return 0;
}

目录的创建

/*
    #include <sys/stat.h>   
    #include <sys/types.h>
    int mkdir(const char *pathname, mode_t mode);
        作用:创建目录
            - pathname:创建的目录名称
            - mode:权限,8进制数
        返回值:成功返回0,失败-1
*/

#include <sys/stat.h>   
#include <sys/types.h>
#include <stdio.h>
int main(){

    int ret = mkdir("aaa", 0777);
    if (ret == -1) {
        perror("mkdir");
        return -1;
    }
    return 0;
}

目录的修改

/*
    #include <unistd.h>
    int chdir(const char *path);
        - 作用:修改进程工作目录
        - 参数:
            - path:需要修改的工作目录 

    #include <unistd.h>
    char *getcwd(char *buf, size_t size);
        - 作用:获取当前工作目录
        - 参数:
            - buf:保存的路径,指向的是一个数组
            - size:数组的大小
        - 返回值:
            返回的指向的一块内存,这个数据就是第一个参数
*/

#include <unistd.h>
#include <stdio.h>
int main(){
    // 获取当前的工作目录
    char buf[128];
    getcwd(buf, sizeof(buf));
    printf("当前的工作目录是:%s\n", buf);
    
    // 修改工作目录
    int ret = chdir("../copy");

    // 获取当前的工作目录
    getcwd(buf, sizeof(buf));
    printf("当前的工作目录是:%s\n", buf);
    return 0;
}

目录重命名

/*
    #include <stdio.h>
    int rename(const char *oldpath, const char *newpath);
        作用:重命名目录
            - oldpath:原名称
            - newpath:新名
        返回值:成功返回0,失败-1
*/

#include <stdio.h>
int main(){

    int ret = rename("aaa", "bbb");
    if (ret == -1) {
        perror("mkdir");
        return -1;
    }
    return 0;
}

目录的打开、遍历、关闭

/*
    #include <sys/types.h>
    #include <dirent.h>
    DIR *opendir(const char *name);
        打开目录
        参数
            - name:需要打开目录的名称
        返回值
            DIR * 类型,目录流
            错误返回NULL

    #include <dirent.h>
    struct dirent *readdir(DIR *dirp);
        读取目录中的数据
        参数
            - dirp 是opendir返回的结果
        返回值
            struct dirent 读取到的文件的信息
            读取到了末尾或者失败,返回NULL

    #include <sys/types.h>
    #include <dirent.h>
    int closedir(DIR *dirp);
        关闭目录
*/
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 读取某个目录下所有的普通文件个数
// ./a.out dirname

int getFileNum(const char *path);

int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("%s path\n", argv[0]);
        return -1;
    }

    int total = getFileNum(argv[1]);
    printf("普通文件的个数为:%d\n", total);
    return 0;
}

// 用户获取目录下所有普通文件的个数
int getFileNum(const char *path) {
    // 打开目录
    DIR *dir = opendir(path);
    if (dir == NULL) {
        perror("opendir");
        printf("%s\n", path);
        exit(0);
    }

    // 记录普通文件个数
    int total;
    struct dirent *ptr;
    
    while ((ptr = readdir(dir)) != NULL) {
        // 获取名称
        char *dname = ptr->d_name;

        // 忽略 ./ ../
        if(strcmp(dname, ".") == 0 || strcmp(dname, "..") == 0) {
            continue;
        }
        // 判断是否是普通文件还是目录
        if(ptr->d_type == DT_DIR) {
            // 目录,需要继续读取这个目录
            char newpath[256];
            sprintf(newpath, "%s/%s", path, dname);
            total += getFileNum(newpath);
        } else if (ptr->d_type == DT_REG) {
            // 普通文件
            total++;
        }
        
    }
    closedir(dir);
    return total;
}

笔记

dup

/*
    #include <unistd.h> 
    int dup(int oldfd);
        复制一个新的文件描述符
        参数:
            - oldfd 需要复制的文件的描述符
    int dup2(int oldfd, int newfd);
*/
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>

int main() {

    int fd = open("a.txt", O_RDWR | O_CREAT, 0664);
    int fd1 = dup(fd);

    if (fd1 == -1) {
        perror("dup");
        return -1;
    }

    printf("fd:%d, fd1:%d\n", fd, fd1);

    close(fd);

    char *str = "hello,world!";
    int ret = write(fd1, str, strlen(str));
    if (ret == -1) {
        perror("write");
        return -1;
    }

    return 0;
}

dup2

/*
    #include <unistd.h> 
    int dup2(int oldfd, int newfd);
        重定向文件描述符
            oldfd 指向a.txt, newfd 指向b.txt
            调用成功后,newfd和b.txt做close,newfd指向a.txt
            oldfd 必须是一个有效的文件描述符
            oldfd和newfd相同,则相当于什么没做

*/
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>

int main() {

    int fd1 = open("1.txt", O_RDWR | O_CREAT, 0664);
    if (fd1 == -1) {
        perror("open");
        return -1;
    }

    int fd2 = open("2.txt", O_RDWR | O_CREAT, 0664);
    if (fd2 == -1) {
        perror("open");
        return -1;
    }

    printf("fd1 : %d, fd2 : %d\n", fd1, fd2);

    int fd3 = dup2(fd1, fd2);
    if (fd3 == -1) {
        perror("dup2");
        return -1;
    }

    // 使用fd3去写数据,实际操作的是1.txt,不是2.txt
    char *str = "hello,world!";
    int len = write(fd2, str, strlen(str));
    if (len == -1) {
        perror("write");
        return -1;
    }

    printf("fd1 : %d, fd2 : %d, fd3 : %d\n", fd1, fd2, fd3);

    close(fd1);
    close(fd2);

    return 0;
}

文件描述符复制、文件flag修改

/*
    #include <unistd.h>
    #include <fcntl.h>
    int fcntl(int fd, int cmd, ... );
    参数
        - fd:需要操作文件的描述符
        - cmd:表示对文件描述符的操作内容
            - F_DUPFD 复制文件描述符,复制第一个 参数,得到一个新的文件描述符(返回值)
                int fd1 = fcntl(fd, F_DUPFD);
            - F_GETFL 获取指定文件描述文件的状态flag
                文件状态flag和通过open函数传递的flag相同
            - F_SETFL 设置文件描述符文件的状态flag
                必选项 O_RDONLY, O_WRONLY, ORDWR 不可以被修改
                可选项 O_APPEND, O_NONBLOCK
                    - O_APPEND 表示追加数据
                    - O_NONBLOCK 设置成不阻塞
    阻塞和非阻塞
        描述的是函数调用的行为。
*/
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
int main() {
    // 复制文件描述符
    // int fd = open("1.txt", O_RDONLY);
    // int ret = fcntl(fd, F_DUPFD);

    // 修改、获取文件的flag
    int fd = open("1.txt", O_RDWR); // 如果是使用O_RDONLY打开文件,后面设置了O_APPEND也无法进行追加
    if (fd == -1) {
        perror("open");
        return -1;
    }
    int flag = fcntl(fd, F_GETFL);
    if (flag == -1) {
        perror("fcntl-F_GETFL");
        return -1;
    }
    int ret = fcntl(fd, F_SETFL, O_APPEND | flag);
    if (ret == -1) {
        perror("fcntl-F_SETFL");
        return -1;
    }
    
    // 写入数据
    const char * str = "nihao";
    write(fd, str, strlen(str));

    close(fd);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值