Linux小练习(1)

一、递归分解目录

将某个目录下的文件全部展示出来,包括文件名、文件大小等信息。

先介绍几个关于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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值