目录
job4/myls.c
- myls.c的功能与系统ls程序相同
- opendir readdir closedir
- 在命令行中输入 man opendir 获取帮助
- 列出指定目录下的文件,例子如下:
$ ./myls job4/test a b c- 列出当前目录下的文件,例子如下:
$ cd job4/test $ ./myls a b c
前置知识
引:先了解一下数据结构!
DIR *dp; // 指向目录
struct dirent *dirp; // 指向目录中的对象
//DIR结构
struct __dirstream
{
void *__fd; /* struct hurd_fd pointer for descriptor. */
char *__data; /* Directory block. */
int __entry_data; /* Entry number __data corresponds to. */
char *__ptr; /* Current pointer into the block. */
int __entry_ptr; /* Entry number __ptr corresponds to. */
size_t __allocation; /* Space allocated for the block. */
size_t __size; /* Total valid data in the block. */
__libc_lock_define (, __lock) /* Mutex lock for this structure. */
};
typedef struct __dirstream DIR;
//dirent结构
struct dirent
{
long d_ino; /* inode number 索引节点号 */
off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
unsigned short d_reclen; /* length of this d_name 文件名长 */
unsigned char d_type; /* the type of d_name 文件类型 */
char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
}
然后了解一下几个关键函数:
1. opendir
头文件:#include <dirent.h>
定义函数:DIR * opendir(const char * name);
函数说明:opendir()用来打开参数name 指定的目录, 并返回DIR*形态的目录流, 和open()类似, 接下来对目录的读取和搜索都要使用此返回值.
返回值:成功则返回DIR* 型态的目录流, 打开失败则返回NULL.
2. readdir
头文件:#include <dirent.h>
定义函数:struct dirent * readdir(DIR * dir);
函数说明:readdir()返回参数dir 目录流的下个目录进入点。
3. closedir
关闭目录啦
实现思路
提取输入字符串,如果为空,则默认当前目录,使用getcwd()获取当前目录路径。
如果不为空,则判断该路径是否存在,若存在就打开该目录,并依次读取目录下的文件名,.与..省略不计。
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
DIR *dp;//指向目录
struct dirent *sdp;//指向目录下对象
if(argv[1]==NULL)//判断参数是否为空
{
char str[80];
getcwd(str,sizeof(str));//直接获取当前地址
dp=opendir(str);//打开目录,指向第一个对象
}
else if((dp=opendir(argv[1]))==NULL)//打开目录,并判断目录是否存在
{
perror("opendir error\n");
exit(1);
}
while((sdp=readdir(dp))!=NULL)//不断读取目录下的内容,指向下一个对象直到为空
{
if(!strcmp(sdp->d_name,".")||!strcmp(sdp->d_name,".."))continue;
printf("%s\t",sdp->d_name);
}
printf("\n");
closedir(dp);
return 0;
}
结果展示
job4/mytree.c
- mytree.c的功能与系统tree程序相同
- 使用空格作为缩进,表示层次
$ ./mytree job4/test test a b x y z c
参考了这位大哥:
9.自己实现linux中的tree - 喵小喵~ - 博客园
前置知识
stat结构体:
struct stat {
dev_t st_dev; //文件的设备编号
ino_t st_ino; //节点
mode_t st_mode; //文件的类型和存取的权限
nlink_t st_nlink; //连到该文件的硬连接数目,刚建立的文件值为1
uid_t st_uid; //用户ID
gid_t st_gid; //组ID
dev_t st_rdev; //(设备类型)若此文件为设备文件,则为其设备编号
off_t st_size; //文件字节数(文件大小)
unsigned long st_blksize; //块大小(文件系统的I/O 缓冲区大小)
unsigned long st_blocks; //块数
time_t st_atime; //最后一次访问时间
time_t st_mtime; //最后一次修改时间
time_t st_ctime; //最后一次改变时间(指属性)
};
主要用到st_mode,表示文件类型:
S_IXUSR 00100 文件所有者具可执行权限
S_ISDIR(st_mode) 是否为目录
sprintf函数:
C 库函数 int sprintf(char *str, const char *format, ...) 发送格式化输出到 str 所指向的字符串。
e.g.
sprintf(str, "Pi 的值 = %f", M_PI);
//str="Pi 的值 = 3.141593"
实现思路
首先输入路径,缺省即获取当前路径。
mytree函数类似于深搜:
- 打开目录,获取文件列表,依次打印文件名
- 对文件名进行判断,如果是目录类型继续深搜,深度+1,并格式化输出文件名;
- deep深度参数用于打印缩进。
- dirc,fc变量用于统计文件数和目录数。
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<dirent.h>
#include<sys/stat.h>
#include<stdlib.h>
int dirc=0,fc=0;
void mytree(char path[],int deep)
{
DIR *dp;//directory point
struct dirent *sdp;//file point
char sonpath[1024];
struct stat f_info;
//struct stat f_info;//file infomation
if((dp=opendir(path))==NULL)
{
perror("opendir error");
exit(1);
}
//open current dictionary and check the error
while((sdp=readdir(dp))!=NULL)
{
stat(sdp->d_name,&f_info);
if(!strcmp(sdp->d_name,".")||!strcmp(sdp->d_name,".."))continue;
for(int i=0;i!=deep;i++)printf("| ");
if(sdp->d_type== DT_DIR)
{
//blue
dirc++;
printf("|----\033[0;32;34m%s\033[0m\n",sdp->d_name);
sprintf(sonpath,"%s/%s",path,sdp->d_name);
mytree(sonpath,deep+1);
//same as dfs
}
else if(f_info.st_mode&00100)//exe filr
{
fc++;
//green
printf("|----\033[1;32m%s\033[0m\n",sdp->d_name);
}
else
{
fc++;
printf("|----%s\n",sdp->d_name);
}
}
closedir(dp);
}
int main(int argc,char* argv[])
{
if(argv[1]==NULL)
{
char str[1024];
getcwd(str,sizeof(str));
printf(".\n");
mytree(str,0);
}
else
{
struct stat file;
stat(argv[1],&file);
if(S_ISDIR(file.st_mode))printf("|----\033[0;32;34m%s\033[0m\n",argv[1]);
else printf("%s\n",argv[1]);
mytree(argv[1],0);
}
if(dirc==1)printf("1 directory, ");
else if(dirc>=2)printf("%d directories, ",dirc);
if(fc==1)printf("1 file.\n");
else if(fc>=2)printf("%d files.\n",fc);
return 0;
}
结果展示
系统的:
我的:
还原度还算高啦!很严谨的!甚至区分了单复数