博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
linux 文件及目录操作 chmod,getcwd,chdir,mkdir,rmdir,opendir,readdir,seekdir,telldir、closedir、stat、fstat
阅读量:2434 次
发布时间:2019-05-10

本文共 7559 字,大约阅读时间需要 25 分钟。

改变目录或文件的访问权限:

#include 
int chmod(const char* path, mode_t mode); //path 参数指定的文件被修改为具有 mode 参数给出的访问权限

获取、改变当前目录:

#include 
//头文件 char *getcwd(char *buf, size_t size); //获取当前目录,相当于 pwd 命令 int chdir(const char *path); //修改当前目录,即切换目录,相当于 cd 命令

getcwd()函数: 将当前的工作目录绝对路径复制到参数 buf 所指的内存空间, 参数 size 为 buf

的空间大小。倘若参数 buf 为 NULL,getcwd()会依参数 size 的大小自动配置内存(使用malloc()),如果参数 size 也为 0,则 getcwd()会 依工作目录绝对路径的字符串程度来决定所配置的内存大小,进程可以在使用完此字符串后自动利用 free()来释放此空间。所以常用的形式:getcwd(NULL, 0)。
chdir()函数:用来将当前的工作目录改变成以参数 path 所指的目录。

#include
int main() {
chdir(“/tmp”); printf(“current working directory: %s\n”,getcwd(NULL,0)); return 0;}

创建和删除目录:

#include 
#include
#include
int mkdir(const char *pathname, mode_t mode); //创建目录,mode 是目录权限 int rmdir(const char *pathname); //删除目录

获取目录信息:

#include 
#include
DIR *opendir(const char *name); //打开一个目录 struct dirent *readdir(DIR *dir); //读取目录的一项信息,并返回该项信息的结构体指针 void rewinddir(DIR *dir); //重新定位到目录文件的头部 void seekdir(DIR *dir,off_t offset); //用来设置目录流目前的读取位置 off_t telldir(DIR *dir); //返回目录流当前的读取位置 int closedir(DIR *dir); //关闭目录文件

seekdir()用来设置参数dir目录流读取位置,在调用readdir()时便从此新位置开始读取。参数offset 代表距离目录文件开头的偏移量。

读取目录信息的步骤为:
1、用 opendir 函数打开目录;
2、使用 readdir 函数迭代读取目录的内容,如果已经读取到目录末尾,又想重新开始读,则可以使用 rewinddir 函数将文件指针重新定位到目录文件的起始位置;
3、用 closedir 函数关闭目录
案例:

#include 
int main(int argc, char* argv[]){
ARGS_CHECK(argc, 2); DIR* dir; dir = opendir(argv[1]); ERROR_CHECK(dir, NULL, "opendir"); struct dirent *p; while(p = readdir(dir)) {
printf("Ino = %ld len = %d type = %d filename = %s\n", p->d_ino, p->d_reclen, p->d_type, p->d_name); } closedir(dir); return 0;}

案例:

#include 
int main(int argc, char* argv[]){
ARGS_CHECK(argc, 2); DIR* dir; dir = opendir(argv[1]); //打开一个目录,返回指向该目录流DIR的指针 ERROR_CHECK(dir, NULL, "opendir"); struct dirent *p; off_t pos; while(p = readdir(dir)) //读取目录的一项信息,并返回该项信息的结构体指针 {
printf("Ino = %ld len = %d type = %d filename = %s\n", p->d_ino, p->d_reclen, p->d_type, p->d_name); if(!strcmp(p->d_name,"a.out")) {
pos = telldir(dir); //返回目录流当前的读取位置 } } seekdir(dir,pos); //重新设置目录流目前的读取位置 printf("~~~~~~~~~~~~~~~~~~~~\n"); p = readdir(dir); printf("Ino = %ld len = %d type = %d filename = %s\n", p->d_ino, p->d_reclen, p->d_type, p->d_name); closedir(dir); //关闭目录文件 return 0;}

DIR的结构体定义如下:

struct __dirstream {
void *__fd; /* `struct hurd_fd' pointer for descriptor. */ char *__data; int __entry_data; char *__ptr; int __entry_ptr; size_t __allocation; size_t __size; __libc_lock_define (, __lock)};typedef struct __dirstream DIR; //DIR的定义

DIR为目录流,类似于于FILE,这种文件包含了其他文件的名称和指向其他文件的文件描述符。通过opendir可以打开该目录流的接口。

opendir()用来打开参数 name 指定的目录,并返回 DIR*形态的目录流,和文件操作函数 open()类
似,接下来对目录的读取和搜索都要使用此返回值。函数失败则返回 NULL。
readdir()函数用来读取目录的信息,并返回一个结构体指针,该指针保存了目录的相关信息。有
错误发生或者读取到目录文件尾则返回 NULL。

struct dirent {
ino_t d_ino; /* inode number(此目录进入点的 inode) */ off_t d_off; /* offset to the next dirent(目录开头到进入点的位移) */ unsigned short d_reclen; /* length of this record(目录名的长度) */ unsigned char d_type; /* type of file(所指的文件类型) */ char d_name[256]; /* filename(文件名) */ };

所有的dirent信息构成的链表(顺序表)为DIR,存在一个指针定位当前所在的链表结点。

每次readdir会移动到链表的下一结点,readdir读取信息后,指针向后偏移,d_off指的是下一个结点的位置。经常用seekdir回到某个位置,而用telldir记录一个位置。
seekdir()函数用来设置目录流目前的读取位置,再调用 readdir()函数时,便可以从此新位置开始
读取。参数 offset 代表距离目录文件开头的偏移量。
telldir()函数用来返回目录流当前的读取位置。

获取文件信息

可以通过 fstat 和 stat 函数获取文件信息,调用完毕后,文件信息被填充到结构体 struct stat
变量中,函数原型为:

#include 
#include
#include
int stat(const char *file_name, struct stat *buf); //文件名 stat 结构体指针 int fstat(int fd, struct stat *buf); //文件描述符 stat 结构体指针

结构体 stat 的定义为:

struct stat {
dev_t st_dev; /*如果是设备,返回设备表述符,否则为 0*/ ino_t st_ino; /* i 节点号 */ mode_t st_mode; /* 文件类型 */ 无符号短整型 nlink_t st_nlink; /* 链接数 */ uid_t st_uid; /* 属主 ID */ gid_t st_gid; /* 组 ID */ dev_t st_rdev; /* 设备类型*/ off_t st_size; /* 文件大小,字节表示 */ blksize_t st_blksize; /* 块大小*/ blkcnt_t st_blocks; /* 块数 */ time_t st_atime; /* 最后访问时间*/ time_t st_mtime; /* 最后修改时间*/ time_t st_ctime; /* 最后权限修改时间 */ };

对于结构体的成员 st_mode,有一组宏可以进行文件类型的判断:

S_ISLNK(mode)  判断是否是符号链接 S_ISREG(mode)  判断是否是普通文件 S_ISDIR(mode)  判断是否是目录 S_ISCHR(mode)  判断是否是字符型设备 S_ISBLK(mode)  判断是否是块设备 S_ISFIFO(mode) 判断是否是命名管道 S_ISSOCK(mode) 判断是否是套接字

案例:

#include
#include
int main() {
struct stat buf; stat (“/etc/passwd”,&buf); printf(“/etc/passwd file size = %d \n”,buf.st_size);//st_size 可以得到文件大小 return 0;} //如果用 fstat 函数实现,如下: int fd = open (“/etc/passwd”,O_RDONLY); //先获得文件描述符fstat(fd, &buf);

案例:以树形结构的形式输出指定目录下面的所有文件

#include 
//自定义的头文件int printDir(char *path, int width){
DIR* dir; dir = opendir(path); ERROR_CHECK(dir, NULL, "opendir"); //自定义的宏 struct dirent *p; char buf[1024]={
0}; while(p = readdir(dir)) {
if (!strcmp(p->d_name, ".")||!strcmp(p->d_name, "..")) {
continue; } printf("%*s%s\n",width,"",p->d_name); sprintf(buf,"%s%s%s",path,"/",p->d_name); if(4 == p->d_type) {
printDir(buf, width+4); } } closedir(dir);}int main(int argc, char* argv[]){
ARGS_CHECK(argc, 2); //自定义的宏 puts(argv[1]); printDir(argv[1], 4); return 0;}

案例:传递任意一个目录路径,能够显示该目录的ls -l的效果

#include 
void printState(char* argv){
int ret; struct stat buf; ret = stat(argv,&buf); //传出参数 //打印文件类型 char file_type = '0'; if(S_ISLNK(buf.st_mode)) file_type = 'l'; else if( S_ISREG(buf.st_mode) ) file_type = '-'; else if( S_ISDIR(buf.st_mode) ) file_type = 'd'; else if( S_ISCHR(buf.st_mode) ) file_type = 'c'; else if( S_ISBLK(buf.st_mode) ) file_type = 'b'; else if( S_ISFIFO(buf.st_mode) ) file_type = 'p'; else if( S_ISSOCK(buf.st_mode) ) file_type = 's'; printf("%c ",file_type); //打印文件权限 char buffer[10]={
0}; char tmp_buf[] = "rwxrwxrwx"; for(int i=0;i<9;i++) {
if(buf.st_mode & (1<<(8-i))) {
buffer[i] = tmp_buf[i]; } else {
buffer[i] = '-'; } } printf("%s",buffer); printf("%ld %s %s %ld %s ",buf.st_nlink,getpwuid(buf.st_uid)->pw_name,getgrgid(buf.st_gid)->gr_name ,buf.st_size,ctime(&buf.st_mtime));}int printDir(char *path){
DIR* dir; dir = opendir(path); ERROR_CHECK(dir, NULL, "opendir"); struct dirent *p; char buf[1024]={
0}; // char buf_t[1024]={0}; while(p = readdir(dir)) {
if (!strcmp(p->d_name, ".")||!strcmp(p->d_name, "..")) {
continue; } sprintf(buf,"%s%s%s",path,"/",p->d_name); char *argv = buf; printState(argv); printf("%s\n",p->d_name); // sprintf(buf,"%s%s%s",path,"/",p->d_name); if(4 == p->d_type) {
printDir(buf); } } closedir(dir);}int main(int argc, char* argv[]){
ARGS_CHECK(argc, 2); printDir(argv[1]); return 0;}

转载地址:http://baxmb.baihongyu.com/

你可能感兴趣的文章
华为云发布三类六款计算实例 打造更强云端计算能力
查看>>
PHP 语言地位遭受挑战,PHP 程序员路在何方?
查看>>
PostgreSQL好评如潮,它是如何做到的?
查看>>
看完这份参会指南,Get 2017 OSC 年终盛典正确参会姿势!
查看>>
盛食厉兵 中科天玑挖掘大数据价值助力行业数字化转型
查看>>
2018年,你所不知道的Jira!
查看>>
2017年,阿里巴巴开源的那些事
查看>>
推动边缘计算的七项核心技术
查看>>
边缘计算精华问答 | 边缘计算需要IaaS、PaaS、SaaS等服务能力吗?
查看>>
Spark精华问答 | Spark 会替代Hadoop 吗?
查看>>
豆瓣已玩烂,来爬点有逼格的 ——IMDB 电影提升你的品位
查看>>
一部刷爆朋友圈的5G短片,看完才知道5G多暖多重要!
查看>>
SDN精华问答 | SDN可以做什么?
查看>>
云评测 | 开发者最有用的开源云监控工具有哪些呢? 这7款神器总有一款适合你!...
查看>>
小团队的微服务之路
查看>>
K8S精华问答 | Kubernetes集群不能正常工作,难道是防火墙问题?
查看>>
5G精华问答 | 什么是5G?5G与LTE有什么关系?
查看>>
虎牙直播在微服务改造方面的实践和总结
查看>>
微服务精华问答 | 在使用微服务架构时,您面临哪些挑战?
查看>>
Kubernetes 调度器实现初探
查看>>