三、文件和目录

三、文件和目录

相关函数

1、stat()

函数功能:获得文件的详细信息,然后存到结构体里。

//man 2 stat   
int stat(const char *pathname, struct stat *statbuf);
//返回值:成功-->0    失败--> -1

stat默认展开符号链接 lstat不展开符号链接(一般用lstat)

struct stat 结构体成员:

struct stat {
    dev_t     st_dev;         /* ID of device containing file 文件本身存储的设备号*/
    ino_t     st_ino;         /* Inode number 线程号*/
    mode_t    st_mode;        /* File type and mode 文件类型 */
    nlink_t   st_nlink;       /* Number of hard links */
    uid_t     st_uid;         /* User ID of owner */
    gid_t     st_gid;         /* Group ID of owner */
    dev_t     st_rdev;        /* Device ID (if special file) 针对驱动的字符设备和块设备文件的主次设备号*/
    off_t     st_size;        /* Total size 文件总大小, in bytes */
    blksize_t st_blksize;     /* Block size for filesystem I/O 块大小 */
    blkcnt_t  st_blocks;      /* Number of 512B blocks allocated 当前文件占用了多少个512个快*/

    /* Since Linux 2.6, the kernel supports nanosecond
       precision for the following timestamp fields.
       For the details before Linux 2.6, see NOTES. */

    struct timespec st_atim;  /* Time of last access */
    struct timespec st_mtim;  /* Time of last modification */
    struct timespec st_ctim;  /* Time of last status change */

#define st_atime st_atim.tv_sec      /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
//man inode "st_mode"

inode --> “st_mode” 用宏进行判断文件类型

S_ISREG(m)  is it a regular file?  常规文件

S_ISDIR(m)  directory?  目录

S_ISCHR(m)  character device?  
 
S_ISBLK(m)  block device?

S_ISFIFO(m) FIFO (named pipe)? 管道类型

S_ISLNK(m)  symbolic link?  (Not in POSIX.1-1996.)

S_ISSOCK(m) socket?  (Not in POSIX.1-1996.)

应用
stat(pathname, &sb);
if (S_ISREG(sb.st_mode)) 
{
    /* Handle regular file */
}
1.1 获取文件长度代码演示:
off_t flen(const char *fname)
{
    struct stat statres;

    if(stat(fname,&statres) < 0)
    {
        perror("stat()");
        exit(1);
    }
    return statres.st_size;
}

int main(int argc,char *argv[])
{
    if(argc < 2)
    {
        fprintf(stderr,"Usage:%s file\n",argv[0]);
        exit(1);
    }

    printf("%lld\n",(long long)flen(argv[1]));
    exit(0);

}
1.2 必须在包含头文件之前实现宏的定义情况

man fseeko

CFLAGS+=-D_FILE_OFFSET_BITS=64 (CFLAGS是编译选项)
//写makefile:
gcc  -D_FILE_OFFSET_BITS=64 
//在命令行:
1.3 权限:st_mode

在这里插入图片描述

man inode

mode_t st_mode 高四位表示文件类型,

获取文件类型:将拿到的文件类型 & 那些宏 如果为真,就表明是那2些文件

用宏测测试文件类型。

S_ISUID     04000   set-user-ID bit
S_ISGID     02000   set-group-ID bit (see below)
S_ISVTX     01000   sticky bit (see below)

S_IRWXU     00700   owner has read, write, and execute permission
S_IRUSR     00400   owner has read permission
S_IWUSR     00200   owner has write permission
S_IXUSR     00100   owner has execute permission

S_IRWXG     00070   group has read, write, and execute permission
S_IRGRP     00040   group has read permission
S_IWGRP     00020   group has write permission
S_IXGRP     00010   group has execute permission

S_IRWXO     00007   others (not in group) have read,  write,  and
                    execute permission
S_IROTH     00004   others have read permission
S_IWOTH     00002   others have write permission
S_IXOTH     00001   others have execute permission
1.4 文件占用大小的问题

命令:du 打印文件在磁盘中真正的占用空间

off_t     st_size;        /* Total size 文件总大小, in bytes */
blksize_t st_blksize;     /* Block size for filesystem I/O 块大小 */
blkcnt_t  st_blocks;      /* Number of 512B blocks allocated 当前文件占用了多少个512个快*/
//size就是一个属性而已,跟后面没有关联

先创建一个5G的空洞文件,然后cp

会发现cp复制的很快,因为cp的原理是先read,cout+=1024,如果全是则不write

1.5 S_ISDIR(m)

判断是否为目录

2、opendir() && readdir()

函数功能:打开一个目录

DIR *opendir(const char *name);
DIR *fdopendir(int fd);
struct dirent *readdir(DIR *dirp);
//返回值:成功-->DIR *   失败-->NULL

代码应用:

#define PATH	"/etc"
int main()
{
	DIR *dp;
	struct dirent *cur;

	dp = opendir(PATH);
	if(dp == NULL)
	{
		perror("opendir()");
		exit(1);
	}

	while((cur = readdir(dp)) != NULL)
	{
		puts(cur->d_name);
	}

	closedir(dp);
	exit(0);
}

3、glob()-读目录

函数功能:用来匹配通配符指定模式的文本值

int glob(const char *pattern, int flags,int (*errfunc) (const char *epath, int eerrno),glob_t *pglob);
//返回值:成功 --> 0  不成功 --> 非0
void globfree(glob_t *pglob); //释放pglob

参数:

  • pattern:通配符指定模式(要解析的通配符)
  • flags:有什么特殊要求
  • 函数:出错的详细信息(在glob出错时调用)
  • pglob:存放结果的空间(前两个,计数器,存放结果的数组)

代码应用:

#define PAT		"/etc/a*.conf"
int myerrfun(const char *epath, int eerrno)
{
	fprintf(stderr,"%s:%s\n",epath,strerror(eerrno);
}

int main()
{
	glob_t globres;
	int i,err;

	err = glob(PAT, 0, NULL/*myerrfun*/, &globres);
	if(err)
	{
		printf("ERROR CODE:%d\n",err);
		exit(1);
	}

	for(i = 0 ; i < globres.gl_pathc ; i++)
	{
		puts(globres.gl_pathv[i]);
	}

	globfree(&globres);
	exit(0);
}

*glob_t pglob结构体:

typedef struct {
     size_t   gl_pathc;    /* Count of paths matched so far 数量 */
     char   **gl_pathv;    /* List of matched pathnames.  路径*/
     size_t   gl_offs;     /* Slots to reserve in gl_pathv.  */
} glob_t;

常用flags:

int flags含义
GLOB_APPEND追加模式(追加到glob_t的尾部)
GLOB_NOCHACK不检查

4、getcwd()

获取当前路径

char *getcwd(char *buf, size_t size);//返回值:

5、getpwuid()

函数功能:给你一个用户的ID,得到全部用户的信息。

struct passwd *getpwuid(uid_t uid);
struct passwd *pwdname;
struct passwd {
    char   *pw_name;       /* username */
    char   *pw_passwd;     /* user password */
    uid_t   pw_uid;        /* user ID */
    gid_t   pw_gid;        /* group ID */
    char   *pw_gecos;      /* user information */
    char   *pw_dir;        /* home directory */
    char   *pw_shell;      /* shell program */
};

6、getgrgid()

函数功能:给你一个组ID,得到全部的组信息。

struct group *getgrgid(gid_t gid);
struct group *pwdgroup;
struct group {
    char   *gr_name;        /* group name */
    char   *gr_passwd;      /* group password */
    gid_t   gr_gid;         /* group ID */
    char  **gr_mem;         /* NULL-terminated array of pointers
                               to names of group members */
};

7、truncate()

文件截断:将一个现有文件长度截断为length,如果该文件以前的长度大于length,则超过length以外的数据将不能够再访问,如果以前的长度小于length,文件长度将增加,文件尾端数据将读0(空洞)

int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);

8、atoi()

函数功能:把一个字符串转换成int

int atoi(const char *nptr);
//The  atoi() function converts the initial portion of the string pointed to by nptr to int.

拓展+练习

1、请写一个程序删除一个文本文件的第十行

4.13 trunstat

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

int main(int argc,char *argv[])
{
	FILE *fd1,*fd2;
	int i=1,j,len_10,oldlen,num_10 = 0;
	char *linebuf = NULL,arr[20];
	ssize_t linesize = 0; //len_10
	char str[100];   //fgets

	if(argc < 2)
	{
		fprintf(stderr,"Usage:%s file\n",argv[0]);
		exit(1);
	}

	fd1 = fopen(argv[1],"r");  
	fd2 = fopen(argv[1],"r+");
	
	fseek(fd1,0,SEEK_END);
	oldlen = ftell(fd1);   //文件总大小 
	printf("oldlen = %d\n",oldlen);
	rewind(fd1);

	while(1) 
	{
		if(getline(&linebuf, &linesize, fd1) < 0 || i == 10)
		{
			len_10 = strlen(linebuf);   //删除前第十行长度
			printf("old_len_10 = %d\n",len_10);
			break;
		}
		num_10 = num_10 + strlen(linebuf); //第十行的位置
		i++;
	}
	
	fseek(fd1,num_10+len_10,SEEK_SET); //11
	fseek(fd2,num_10,SEEK_SET);        //10
	printf("delele\n");

	while(fgets(str,20,fd1) != NULL)   //11 --> 10 
		fputs(str,fd2);

	truncate(argv[1],oldlen-len_10);   //delete
	rewind(fd1);
	
	while(1)  //验证
	{
		 if(getline(&linebuf, &linesize, fd1) < 0 || j == 10)
		 {
			 printf("new_len_10 = %ld\n",strlen(linebuf));  //删除后的文件的第十行长度
			 break;
		 }
		i++;
	}
	exit(0);

	fclose(fd1);
	fclose(fd2);
}

2、实现mudu

ls -a

#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <glob.h>
#include <stdio.h>
#include <stdlib.h>

#define PATH "./"
int path_no_loop(const char *path)
{
	char *pos;
	pos = strrchr(path,'/');
	if(strcmp(pos+1,".") == 0 || strcmp(pos+1,"..") == 0 )
		return 0;
	return 1;
}


int64_t my_du(const char*path)
{
	struct stat statres;
	int i;
	int64_t sum = 0;
	char nextpath[1024];
	glob_t globres;
	
	if(lstat(path,&statres) < 0)
	{
		perror("lstat()");
		exit(1);
	}
	//not is dir
	if(!S_ISDIR(statres.st_mode))
		return statres.st_blocks;
	//is dir
	strncpy(nextpath,path,1024);
	strncat(nextpath,"/*",1024);
	glob(nextpath,0,NULL,&globres);

	strncpy(nextpath,path,1024);
	strncat(nextpath,"/.*",1024);
	glob(nextpath,GLOB_APPEND,NULL,&globres);

	for( i=0;i < globres.gl_pathc;i++)
	{	
		if(path_no_loop(globres.gl_pathv[i]))
			sum += my_du(globres.gl_pathv[i]);
	printf("%d  %s\n",statres.st_blocks/2,globres.gl_pathv[i]);
	}
	
	sum += statres.st_blocks;

	return sum; 
}

int main(int argc,char *argv[])
{
	int i,err,num = 0;
	glob_t globres;

	printf("%ld\n",my_du(argv[1])/2);

	exit(0);
}

3、strrchr()

在参数 str 所指向的字符串中搜索最后一次出现字符 c(一个无符号字符)的位置。

char *strrchr(const char *str, int c)
//该函数返回 str 中最后一次出现字符 c 的位置。如果未找到该值,则函数返回一个空指针。
char *pos;
pos = strrchr(globres.gl_pathv[i],'/');

参数:

  • str – C 字符串。
  • c – 要搜索的字符。以 int 形式传递,但是最终会转换回 char 形式。

tail -f 以动态的形式查看文件尾部的变化

4、strchr()

在参数 s 所指向的字符串中搜索第一次出现字符 c(一个无符号字符)的位置。

char *strchr(const char *s, int c);
//该函数返回在字符串 str 中第一次出现字符 c 的位置,如果未找到该字符则返回 NULL。

5、广义表转换成二叉树

广义表 -----> tree.log

struct node_st *load(FILE *fp)
{   
    int ch;
    ch = fgetc(fp);
    struct node_st *root;
    
    if(ch != '(')
    {
        fprintf(stderr,"read error().\n");
        return NULL;
    }
    
    ch = fgetc(fp);
    if(ch == ')')
        return NULL;
    
    root = malloc(sizeof(*root));
    root->data = ch;
    root->l = load(fp);
    root->r = load(fp);
    
    fgetc(fp);  //(
    
    return root;
}

struct node_st *tree_list(const char *path)
{
    FILE *fp;
    struct node_st *root;

    fp = fopen(path,"r");
    /* if error*/
    root = load(fp);
    fclose(fp);

    return root;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值