Linux下的ls命令详解以及C语言实现

一、众所周知,ls是linux下最常用的命令之一,使用起来也相当的快捷与方便,ls 命令将每个由 Directory 参数指定的目录或者每个由 File 参数指定的名称写到标准输出,以及您所要求的和标志一起的其它信息。如果不指定 File 或 Directory 参数, ls 命令显示当前目录的内容。

使用语法如下:

ls (options) (参数)

1、options即为选项,常见的选项有如下…

-a:显示所有档案及目录(ls内定将档案名或目录名称为“.”的视为影藏,不会列出);

-A:显示除影藏文件“.”和“..”以外的所有文件列表;

-F:在每个输出项后追加文件的类型标识符,具体含义:“*”表示具有可执行权限的普通文件,“/”表示目录,“@”表示符号链接,“|”表示命令管道FIFO,“=”表示sockets套接字。当文件为普通文件时,不输出任何标识符;

-b:将文件中的不可输出的字符以反斜线“”加字符编码的方式输出;

-f:此参数的效果和同时指定“aU”参数相同,并关闭“lst”参数的效果;

-k:以KB(千字节)为单位显示文件大小;

-l:以长格式显示目录下的内容列表。输出的信息从左到右依次包括文件名,文件类型、权限模式、硬连接数、所有者、组、文件大小和文件的最后修改时间等;

-r:以文件名反序排列并输出目录内容列表;

-s:显示文件和目录的大小,以区块为单位;

-t:用文件和目录的更改时间排序;

-L:如果遇到性质为符号链接的文件或目录,直接列出该链接所指向的原始文件或目录;

-R:递归处理,将指定目录下的所有文件及子目录一并处理;

注:选项可以多个进行组合使用,具体可实践查看效果。

2、参数
参数为要显示的路径或文件,如不指定则为当前路径。

二、运用C语言实现(ls -l path)

1、在shell中键入:ls -l , 查看效果如下…
这里写图片描述

2、以下为C代码实现

/*
 *实现ls -l的shell命令
 */

#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<dirent.h>
#include<grp.h>
#include<pwd.h>
#define NAME_SIZE 20

struct fnode
{
    struct fnode *next ; //下一个成员
    char name[NAME_SIZE] ; //当前成员文件名
} ;

struct fnode* insert_list(struct fnode *node , struct fnode *linklist) ; //将节点插入链表中

void output_info(struct fnode *head) ; //输出文件信息

void output_type_perm(mode_t mode) ; //列出文件的权限和类型字符

void output_user_group(uid_t uid , gid_t gid) ; //列出用户及用户信息

void output_mtime(time_t mytime) ; //列出各文件基本信息

void myfree(struct fnode *linklist) ; //释放内存

int main(int argc , char* argv[])
{
    if(argc < 2)
    {
        printf("usage : %s dir_name \n" , argv[0]) ;
        exit(EXIT_FAILURE) ;
    }

    int i ;
    for(i = 1 ; i < argc ; i++)
    {
        struct fnode *linklist = NULL ;
        struct stat stat_info ;

        if(stat(argv[i] , &stat_info) == -1)
        {
            perror("stat") ;
            exit(EXIT_FAILURE) ;
        }

        printf("argv[i] is : %s \n" , argv[i]) ;

        if(S_ISREG(stat_info.st_mode)) //普通文件
        {
            printf("It is a normal file\n") ;
            struct fnode *temp = (struct fnode*) malloc(sizeof(struct fnode)) ; //为当前文件结构申请内存空间

            if(temp == NULL)
            {
                perror("malloc error") ;
                exit(EXIT_FAILURE) ;
            }
            temp->next = NULL ;

            //将当前文件名拷贝到temp->name中
            memset(temp->name , '\0' , NAME_SIZE) ;
            memcpy(temp->name , argv[i] , strlen(argv[i])) ;
            linklist = insert_list(temp , linklist) ; //将该文件插入linklist中
            output_info(linklist) ; //输出文件的所有信息
        }
        else if(S_ISDIR(stat_info.st_mode)) //是否是路径
        {
            printf("It is a dir \n") ;

            char buf[NAME_SIZE] ; 
            getcwd(buf , 128) ; //获取当前工作路径并将其拷贝到buf中
            DIR *dirp = NULL ;
            dirp = opendir(argv[i]) ; //打开当前路径
            if(dirp == NULL)
            {
                perror("open dir") ;
                exit(EXIT_FAILURE) ;
            }
            struct dirent *entp = NULL ;
            while(entp = readdir(dirp))
            {
                struct fnode *temp = (struct fnode *)malloc(sizeof(struct fnode)) ;
                if(temp == NULL)
                {
                    perror("malloc") ;
                    exit(EXIT_FAILURE) ;
                }
                temp->next = NULL ;
                memset(temp->name , '\0' , NAME_SIZE) ;
                memcpy(temp->name , entp->d_name , strlen(entp->d_name)) ;
                linklist = insert_list(temp , linklist) ;
            }
            chdir(argv[i]) ; //改变当前路径
            close(dirp) ;
            output_info(linklist) ;
            chdir(buf) ;
        }
        myfree(linklist) ;
    }
    return 0 ;
}       

void output_type_perm(mode_t mode)
{
    char type[7] = {'p' , 'c' , 'd' , 'b' , '-' , 'l' , 's'} ;
    int index = ((mode >> 12) & 0xF) / 2 ;
    printf("%c" , type[index]) ;

    char *perm[8] = {"---" , "--x" , "-w-" , "-wx" , "r--" , "r-x" , "rw-" , "rwx"} ;
    printf("%s" , perm[mode >> 6 & 07]) ;
    printf("%s" , perm[mode >> 3 & 07]) ;
    printf("%s" , perm[mode >> 0 & 07]) ;
}

void output_user_group(uid_t uid , gid_t gid)
{
    struct passwd *user ;
    user = getpwuid(uid) ;

    printf(" %s" , user->pw_name) ;

    struct group *group ;

    group = getgrgid(gid) ;
    printf(" %s" , group->gr_name) ;
}

void output_mtime(time_t mytime)
{
    char buf[256] ;
    memset(buf , '\0' , 256) ;
    ctime_r(&mytime , buf) ;
    buf[strlen(buf) - 1] = '\0' ;
    printf(" %s" , buf) ;
}

void output_info(struct fnode *head)
{
    struct fnode *temp = head  ;
    while(temp != NULL)
    {
        struct stat mystat ;
        if(stat(temp->name , &mystat) == -1)
        {
            perror("stat") ;
            exit(EXIT_FAILURE) ;
        }
        output_type_perm(mystat.st_mode) ;
        printf(" %4d" , mystat.st_mode) ;
        output_user_group(mystat.st_uid , mystat.st_gid) ;
        printf(" %8ld" , mystat.st_size) ;
        output_mtime(mystat.st_mtime) ;
        printf(" %s\n" , temp->name) ;
        temp = temp->next ;
    }
}

struct fnode * insert_list(struct fnode* temp , struct fnode * linklist)
{
    if(linklist == NULL)
    {
        linklist = temp ;
    }
    else
    {
        struct fnode *node ;
        node = linklist ;
        while(node->next != NULL)
        {
            node = node->next ;
        }
        node->next = temp ;
    }
    return linklist ;
}

void myfree(struct fnode *linklist)
{
    struct fnode *temp ;
    temp = linklist ;
    while(temp != NULL)
    {
        temp =  linklist->next ;
        free(linklist) ;
        linklist = temp ;
    }
}

运行查看效果…

这里写图片描述

其中的warning一直无解,明明将头文件导入,但总是提示函数未加声明,但是不影响运行结果,如果有大神,还请不吝赐教…

myls命令包含9个选项: (1) myls : 在缺省选项的情况下,列出当前文件夹下的普通文件(不包含隐藏文件)。 例如:当前目录包含文件home1.c, home2.c, .home3.c,输入myls后,列出的文件名为home1.c, home2.c. (2) myls –a: 列出当前文件夹下的所有文件(包含隐藏文件)。 例如:当前目录包含文件home1.c、home2.c、.home3.c,输入myls -a后,列出所有的文件名为home1.c, home2.c, .home3.c. (3) myls –l: 列出当前文件夹下普通文件的详细信息,包括文件模式,文件链接数,文件所属用户,文件所属用户组,文件大小,文件最后修改时间,文件名。并且在最后一行显示该目录下所显示的文件的文件块数。 例如:显示drwxr-xr-x 3 eli eli 4096 Nov 16 23:07 Desktop (4) myls -R 递归列出文件及其子文件。 例如:当前目录为home, 其中包含文件home1, home2, home3. 其中home1是目录文件,包含文件home11, home12, home2不是目录文件,home3是目录文件,包含文件home31, home32。 输入myls –R后,列出的文件名为 ./home: home1 home2 home3 ./home/home1: home11 home12 ./home/home3: home31 home32. (5) myls –u: 列出当前文件夹下用户x的普通文件,若输入myls -u bb,则显示所属bb的普通文件。 例如:文件home1, home2, home3属于aa,文件tmp1, tmp2, tmp3属于bb, 则若输入myls –u aa, 则显示home1,home2,home3,若输入myls -u bb, 则显示tmp1,tmp2,tmp3。 (6) myls –S: 对文件进行排序,需要输入比较参数。 myls –S 的参数包括: time——按最近修改时间排序 name——按文件名的字典序排序 size——按文件的大小从小到大排序 link——按文件链接数从少到多排序 (7) myls -1: 将当前文件夹下的文件按照一行一个的方式显示。 (8) myls –s: 在各个文件开头显示这个文件的文件块大小。 (9) myls /dirname: 显示/dirname下的文件。 编译 gcc main.c -o myls 执行 ./myls 可加若干参数,具体见上描述 程序并不完整,可能会有BUG,希望广大网友指点,交流~
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值