(实验3)文件与目录操作

1.文件与目录的实验内容

  • 仿写ls -l的功能(编写myls程序) ,参数通过命令行传入:
    1.获取当前工作目录路径并对该目录实现遍历
    2.仿ls -l以列表形式,列出当前工作目录下的所有文件(包括子目录)
  • 需显示的文件属性有:
    文件类型 权限 硬链接数 所有者用户名 所有者所在组用户名 文件大小 最后修改时间
    在这里插入图片描述

2.ls -l的功能分析

在这里插入图片描述

  • 流程图如下
    在这里插入图片描述

3.获取当前的工作路径

头文件: unistd.h

函数定义: char *getcwd(char *buf, size_t size)
分配一个内存区buf, 存储当前工作路径字符串。 
Size则是buf 大小(该内存区需要手动释放) , 失败返回NULL

函数定义: char *get_current_dir_name(void)
成功返回路径字符串缓冲区指针(该内存区需要手动释放) ,失败返回NULL

4.打开关闭目录函数

常用函数: opendir, closedir
头文件: dirent.h

函数定义: DIR * opendir(const char * name);
打开name指定的目录, 并关联一个目录流(类似于C库函数中的文件流)
失败返回NULL

函数定义: int closedir(DIR *dir);
关闭指定目录流, 释放相关数据结构
成功返回0;失败返回-1

5.读取目录文件函数

头文件: sys/types.h; dirent.h
函数定义: struct dirent * readdir(DIR *dir) 读取目录流dir标识的目录下文件
到达文件结尾或者错误发生, 返回NULL

If((currentdir = opendir(buf))==NULL)
{ 
	printf(open directory fail \n”);
	return 0; 
}
else 
{ 
	printf(file in directory include: \n”);
	while((currentdp = readdir(currentdir)!=NULL)
		printf(%s\n”,currentdp->d_name); 
}

在这里插入图片描述
在这里插入图片描述

6.读取目录文件函数:dirent结构

struct dirent
{
	ino_t d_ino; i节点号
	off_t d_off; 在目录文件中的偏移
	usigned short d_reclen; 文件名长度
	unsigned char d_type; 文件类型
	char d_name[256]; 文件名,重要
};
  • printf(“%s\n”,currentdp->d_name);结果如下
    在这里插入图片描述

7.获取文件属性

常用函数: stat, lstat
头文件: sys/stat.h

函数定义: int stat(const char *path, struct stat *buf);
int lstat(const char *path, struct stat *buf);
函数作用: 读取path参数指定文件的文件属性, 填充到buf参数指向的结构体

区别: 
前提:若path是符号链接
lstat返回符号链接的文件属性
stat返回符号链接引用文件的文件属性
  • 存储文件属性的stat结构
struct stat 
{
	mode_t st_mode; 文件类型与访问权限,重要
	ino_t st_ino; i节点号
	dev_t st_dev; 文件使用的设备号
	dev_t st_rdev; 设备文件的设备号
	nlink_t st_nlink; 文件的硬链接数,重要
	uid_t st_uid; 文件所有者用户ID,重要
	gid_t st_gid; 文件所有者组ID,重要
	off_t st_size; 文件大小(以字节为单位),重要
	time_t st_atime; 最后一次访问该文件的时间
	time_t st_mtime; 最后一次修改该文件的时间,重要
	time_t st_ctime; 最后一次改变该文件状态的时间
	blksize_t st_blksize; 包含该文件的磁盘块的大小
	blkcnt_t st_blocks; 该文件所占的磁盘块数
};

8.解析st_mode的内容

mode_t st_mode;
  • 无符号整数,其低16位定义如下
    在这里插入图片描述
    (1)对于文件类型域而言
    在这里插入图片描述

(2)对于文件访问权限而言
在这里插入图片描述

  • st_mode的宏
(1)从st_mode中获取文件类型
S_ISREG(st_mode)的原理如下:
#define S_IFMT 0170000
#define S_IFREG 0100000
#define S_ISREG(m)
(((m)&S_IFMT)==S_IFREG)

宏:S_XXXX(file)

✓ 是否为普通文件: S_ISREG(st_mode)
✓ 是否为目录文件 S_ISDIR(st_mode)
✓ 是否为字符设备 S_ISCHR(st_mode)
✓ 是否为块设备 S_ISBLK(st_mode)
✓ 是否为FIFO S_ISFIFO(st_mode)
✓ 是否为套接字 S_ISSOCK(st_mode)
✓ 是否为符号连接 S_ISLINK(st_mode)

eg:
if(S_ISREG(buf.st_mode))
	ptr = "regular";2)从st_mode中获取读写权限
✓ S_IRWXU 00700 文件所有者的权限值组合
✓ S_IRUSR 00400 文件所有者具可读取权限
✓ S_IWUSR 00200 文件所有者具可写入权限
✓ S_IXUSR 00100 文件所有者具可执行权限
✓ S_IRWXG 00070 用户组的权限值组合
✓ S_IRGRP 00040 用户组具可读取权限
✓ S_IWGRP 00020 用户组具可写入权限
✓ S_IXGRP 00010 用户组具可执行权限
✓ S_IRWXO 00007 其他用户的权限值组合
✓ S_IROTH 00004 其他用户具可读取权限
✓ S_IWOTH 00002 其他用户具可写入权限
✓ S_IXOTH 00001 其他用户具可执行权限

eg:
if ((S_IRUSR & st_mode) == S_IRUSR)
{
	printf("r");
}

9.获取用户属性函数

常用函数: getpwuid
头文件: sys/types.h, pwd.h

函数定义:
struct passwd *getpwuid(uid_t uid);
输入用户ID,返回用户属性信息(passwd结构)

struct passwd
{
	char *pw_name; /* 用户名*/
	char *pw_passwd; /* 密码.*/
	__uid_t pw_uid; /* 用户ID.*/
	__gid_t pw_gid; /*组ID.*/
	char *pw_gecos; /*真实名*/
	char *pw_dir; /* 主目录.*/
	char *pw_shell; /*使用的shell*/
};

10.获取文件时间信息

常用函数: localtime, ctime
头文件: time.h

函数定义: 
struct tm* localtime(const time_t *lock)
localtime返回tm结构体指针(存储时间的年月日各个量)

char* ctime(const time_t *timep)
ctime直接解析为当地时间格式例如“wed jun 30 21:49:08 1993\n”

11.linux编程技巧:缓冲区分配

  • 数组缓冲区和指针缓冲区的区别
申明全局数组变量				申明全局指针变量
申明即可						malloc分配空间,free释放空间
位置:栈						位置:堆
作用于所有函数				作用于所有函数
进程生命周期					malloc之后,free之前

注意:局部数组变量(即:局部数组缓冲区)和指针变量(即:局部指针缓冲区)的比较大同小异,只是作用范围及生命周期都缩减为申明函数之内
  • eg如下:
数组缓冲区:
char buffer[100];
int buffer[100];
buffer为缓冲区

指针缓冲区:
char *buffer=NULL;
buffer=(char *)(malloc(100*sizeof(char)));
...
free(buffer);
buffer=NULL;

12.编写代码如下:

char *buffer=NULL;
buffer=(char *)(malloc(100*sizeof(char)));
FILE *currentdir;
struct dirent* currentdp;
struct stat currentstat;

//获取但概念目录路径
if (getcwd(buffer,100*sizeof(char))!=NULL)
	printf("%s\n", buf);

//打开当前目录,并判断是否成功
if ((currentdir=opendir(buffer))==NULL)
{
	printf("open directory fail\n");
	return 0;
}

/读取当前目录下的目录项,并判断是否成功
while((currentdp=readdir(currentdir))!=NULL)
{
	if (currentdp->d_name[0]!='.')
	{
		//读取当前文件的信息,并判断是否成功
		if (stat(buffer, &currentstat)!=0)
		{
			printf("get stat srror\n");
			continue;
		}
		printf_type(currentstat.st_mode);
		printf_perm(currentstat.st_mode);
		printf_link(currentstat.st_nlink);
		printf_usrname(currentstat.st_uid);
		printf_grname(currentstat.st_gid);
		printf_time(currentstat.st_mtime);
		printf_filename(currentstatdp);
	}
}
closedir(currentdir);
return 0;

void printf_type(mode_t perm)
{
	char str[1]={0};
	if(S_ISREG(sbuf.st_mode))  str[0] = '-';
	if(S_ISDIR(sbuf.st_mode))  str[0] = 'd';
	if(S_ISCHR(sbuf.st_mode))  str[0] = 'c';
	if(S_ISBLK(sbuf.st_mode))  str[0] = 'b';
	if(S_ISFIFO(sbuf.st_mode)) str[0] = 'p';
	if(S_ISLNK(sbuf.st_mode))  str[0] = 'l';
	if(S_ISSOCK(sbuf.st_mode)) str[0] = 's';
	
	printf("%s\n", str);
}

#define STR_SIZE sizeof("rwxrwxrwx")
void printf_perm(mode_t perm)
{
	char str[STR_SIZE];
	snprintf(str, STR_SIZE, "%c%c%c%c%c%c%c%c%c",
        (perm & S_IRUSR) ? 'r' : '-', (perm & S_IWUSR) ? 'w' : '-',
        (perm & S_IXUSR) ? 'x':'-',
        (perm & S_IRGRP) ? 'r' : '-', (perm & S_IWGRP) ? 'w' : '-',
        (perm & S_IXGRP) ?'x':'-',
        (perm & S_IROTH) ? 'r' : '-', (perm & S_IWOTH) ? 'w' : '-',
        (perm & S_IXOTH) ?'x':'-');
}

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
以下是仿写Linux下的ls-l命令的Python代码: ```python import os import pwd import grp import time def ls_l(path='.'): # 获取当前目录下的所有文件目录 files = os.listdir(path) # 遍历所有文件目录 for file in files: file_path = os.path.join(path, file) stat_info = os.stat(file_path) # 获取文件权限 mode = stat_info.st_mode file_perm = '' if os.path.isfile(file_path): file_perm += '-' elif os.path.isdir(file_path): file_perm += 'd' else: file_perm += '?' if mode & 0o400: file_perm += 'r' else: file_perm += '-' if mode & 0o200: file_perm += 'w' else: file_perm += '-' if mode & 0o100: file_perm += 'x' else: file_perm += '-' if mode & 0o040: file_perm += 'r' else: file_perm += '-' if mode & 0o020: file_perm += 'w' else: file_perm += '-' if mode & 0o010: file_perm += 'x' else: file_perm += '-' if mode & 0o004: file_perm += 'r' else: file_perm += '-' if mode & 0o002: file_perm += 'w' else: file_perm += '-' if mode & 0o001: file_perm += 'x' else: file_perm += '-' # 获取文件所有者和所属组 uid = stat_info.st_uid gid = stat_info.st_gid try: owner = pwd.getpwuid(uid).pw_name except KeyError: owner = str(uid) try: group = grp.getgrgid(gid).gr_name except KeyError: group = str(gid) # 获取文件大小 size = stat_info.st_size # 获取文件最后修改时间 mtime = stat_info.st_mtime mtime_str = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(mtime)) # 输出文件信息 print('{} {} {} {} {} {}'.format(file_perm, owner, group, size, mtime_str, file)) ``` 使用示例: ```python ls_l('.') # 显示当前目录下的文件信息 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喜欢打篮球的普通人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值