一、递归分解目录
将某个目录下的文件全部展示出来,包括文件名、文件大小等信息。
先介绍几个关于linux目录操作的函数。
DIR* open(const char* fileName);
函数说明:
(1)作用:打开一个目录。
(2)参数:目录路径名。
(3)返回值:成功:DIR*是一个文件指针(结构体),其中包括文件的一些特有的信息,例如文件(目录)大小等。
失败:NULL
struct dirent * readdir(DIR* dir);
函数说明:
(1)作用:打开目录。
(2)参数:DIR指针
(3)返回值:成功:返回记录项或者NULL,失败返回-1.
close(DIR* dir);
(1)作用:关闭目录。
思路:
(1)判断当前文件的类型是否为目录:
如果是,就将改目录该目录分解,在将结果回传打印。
如果不是就直接打印。
代码:
环境:CentOS(Linux)+ Gcc
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
void showFileDir(char* filename);
char* decDir(char* dirname);
//递归
//分解目录
char* decDir(char* dirname)
{
DIR* dir;
struct dirent *pDir;
dir=opendir(dirname);
if(dir==NULL)
{
printf("没有权限操作文件:%s\n",dirname);
}
while((pDir=readdir(dir))!=NULL)
{
if(strcmp(pDir->d_name,".")==0||strcmp(pDir->d_name,"..")==0)
{
continue;
}
char tempDirName[1024];
//不能简单的赋值(浅拷贝)
strcpy(tempDirName,dirname);
//每次读出的数据是一个文件名,需要将其补为绝对路径
strcat(strcat(tempDirName,"/"),pDir->d_name);
showFileDir(tempDirName);
}
closedir(dir);
}
//展示当前目录下的文件
void showFileDir(char* filename)
{
struct stat fileFlag;
if(stat(filename,&fileFlag)==-1)
{
perror(filename);
return;
}
//如果当前文件类型为目录,展开,回调。
if((fileFlag.st_mode & __S_IFMT)==__S_IFDIR)
{
printf("目录:%s\n",filename);
decDir(filename);
}
else
{
//如果当前文件类型为普通文件直接打印。
printf("%-8d%-4d%s\n",fileFlag.st_uid,fileFlag.st_size,filename);
}
}
int main(int argc,char* argv[])
{
if(argc<2)
{
printf("showDir+filename");
exit(1);
}
int i=1;
while(i<argc)
{
showFileDir(argv[i++]);
}
return 0;
}
二、实现ls -l的部分功能(显示用户和用户组)。
通过stat()函数我们可以得到文件的绝大多数信息,但有些信息不是直接给出的而是给出了代号,想用户和用户组就是给出了uid和gid,而不直接给出具体的信息。一般情况下用户的这些信息是保存在/ect/passwd下(也就是存放密码的地方,当然,密码经过了不可逆的加密)。我们需要通过读取每一行的信息,然后从中解析出该文件的编号对应的用户和用户组。
环境:CentOS+Gcc
代码:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 1024
//返回一个指针数组,每个指针指向一个字符串
void decString(char* str,int len,char pstrSub[][SIZE])
{
char temp[SIZE];
int i=0,j=0,k=0;
//将内容按":"分割
for(;i<len;++i)
{
if(str[i]!=':')
{
temp[j]=str[i];
++j;
}
else
{
temp[j]='\0';
strcpy(pstrSub[k],temp);
if(k==4)
{
break;
}
++k;
j=0;
}
}
}
int main(int argc,char* argv[])
{
if(argc<2)
{
printf("请输入文件");
exit(1);
}
struct stat buf;
if((stat(argv[1],&buf))<0)
{
perror("stat");
}
//printf("%u",buf.st_mode);
char *uname,*gname;
int fileFlag=open("/etc/passwd",O_RDONLY);
if(fileFlag<0)
{
perror("/etc/passwd");
}
int i=0;
char fileBuf[SIZE];
//由于linux中没有readlink()类似功能的函数,所以一个一个字符读入.
while(read(fileFlag,fileBuf+i,1))
{
if(fileBuf[i]=='\n')
{
//加上结束标志
fileBuf[i]='\0';
//按:将字符串进行分割
char strSub[5][SIZE];
//将二维数组通过参数传入
decString(fileBuf,i,strSub);
if(atoi(strSub[2])==buf.st_uid)
{
uname=strSub[0];
gname=strSub[4];
break;
}
i=-1;
}
++i;
}
printf("文件名:%s文件大小:%d用户:%s用户组:%s\n",argv[1],buf.st_size,uname,gname);
return 0;
}