文章目录

  • ​​1.文件与目录的实验内容​​
  • ​​2.ls -l的功能分析​​
  • ​​3.获取当前的工作路径​​
  • ​​4.打开关闭目录函数​​
  • ​​5.读取目录文件函数​​
  • ​​6.读取目录文件函数:dirent结构​​
  • ​​7.获取文件属性​​
  • ​​8.解析st_mode的内容​​
  • ​​9.获取用户属性函数​​
  • ​​10.获取文件时间信息​​
  • ​​11.linux编程技巧:缓冲区分配​​
  • ​​12.编写代码如下:​​

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

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

2.ls -l的功能分析

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

  • 流程图如下

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);
}

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


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

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)对于文件访问权限而言

(实验3)文件与目录操作_函数定义_04

  • 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, ¤tstat)!=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':'-');
}