您的位置:首页 > 编程语言 > C语言/C++

ls的C语言实现

2014-02-26 19:09 330 查看
/* 
    Name: list.c 
    Author: guozan _SCS_BUPT 
    Mail: guozan523@foxmail.com 
    Date: 2010/4/6 
    实验目的:练习vi,使用UNIX的系统调用和库函数,体会UNIX文件通配符的处理方式以及命令对选项的处理方式。 
    编程实现程序list.c,列表普通磁盘文件(不考虑目录和设备文件等),列出文件名和文件大小。 
    与ls命令类似,命令行参数可以有0到多个 
    0个参数:列出当前目录下所有文件 
    参数为普通文件:列出文件 
    参数为目录:列出目录下所有文件 
    实现自定义选项r,a,l,h,m以及-- 
    r 递归方式列出子目录 
    a 列出文件名第一个字符为圆点的普通文件(默认情况下不列出文件名首字符为圆点的文件) 
    l 后跟一整数,限定文件大小的最小值(字节) 
    h 后跟一整数,限定文件大小的最大值(字节) 
    m 后跟一整数n,限定文件的最近修改时间必须在n天内 
    --  显式地终止命令选项分析 
*/  
#include <sys/stat.h>   
#include <sys/types.h>
  
#include <dirent.h>   
#include <unistd.h>
  
#include <stdio.h>   
#include <string.h>
  
/* 
    slective options about ls 
    rflag is about recursive 
    aflag is about ones with . infront 
    lflag is about the minimum size 
    hflag is about the maximum size 
    mflag is about the modified time 
*/  
int rflag, aflag, lflag, hflag, mflag;  
long modified_time;        //the last time file be modified, days ago
  
off_t lower_size;            //file's minimum size
  
off_t upper_size;            //file's maximum size
  
/* 
    set the flags, thus the ls option 
*/  
void getoptions(int argc, char *argv[])  
{  
    char ch;  
    //clear, all unseted   
    rflag = 0; aflag = 0; lflag = 0; hflag = 0; mflag = 0;  
    //use getopt to get the options, want to know more, call man
  
    //the last one or after -- was set in argv[optind]
  
    while ((ch = getopt(argc, argv, "ral:h:m:")) != -1) {  
        switch (ch) {  
            case 'r': rflag = 1; break;  
            case 'a': aflag = 1; break;  
            case 'l': lflag = 1; lower_size = atol(optarg); break;  
            case 'h': hflag = 1; upper_size = atol(optarg); break;  
            case 'm': mflag = 1; modified_time = atol(optarg); break;    //get days
  
            case '?': printf("Unknown option: %c/n", (char)optopt); break;  
            default : printf("Step into default/n"); break;  
        }  
    }  
}  
/* 
    the function to list things in path 
*/  
int ls(char *path)  
{  
    struct stat st;        //for check this is a directory or file
  
    char temp[100];        //if path is null, it is used to get current directory
  
    // get the path   
    if (path == NULL || path[0] == '-') {  
        path = temp;  
        getcwd(path, 100);  
    }  
    /* open the inode of file */  
    if (lstat(path, &st)) {  
        fprintf(stderr, "Error: %s not exist./n", path);  
        return (-1);  
    }  
    /* judge whether the file is a file or a directory */  
    if (S_ISDIR(st.st_mode)) {  
        ls_dir(path);  
    }  
    else if (S_ISREG(st.st_mode)) {  
        print(path);  
    }  
    else {  
        printf("Not ordinary file, wouldn't be listed./n");  
    }  
    return 0;  
}  
/* 
    list dirs, may recursively or not, depending on rflag 
    one thing is sure that it will list directories and files first, 
    then consider the things in the directories 
*/  
int ls_dir(char *path)  
{  
    DIR *dp = NULL;  
    struct dirent *dirp = NULL;  
    if (path[0] != '.' || (path[0] == '.' && aflag == 1)) {  
        printf("/n%s:/n****************************************/n", path);  
        /* open the directory */  
        if ((dp = opendir(path)) == NULL) {  
            fprintf(stderr, "Error: can't open directory %s!/n", path);  
            return (-1);  
        }  
        chdir(path);  
        /* list all the things in directory */  
        while ((dirp = readdir(dp)) != NULL) {  
            print(dirp->d_name);  
        }  
        /* recursively ls dirs, after ls things together, 
            it's time to list things in children directory */  
        if (rflag == 1) {  
            rewinddir(dp);    //reset dp
  
            while ((dirp = readdir(dp)) != NULL) {  
                if (strcmp(dirp->d_name, ".") == 0  
                    || strcmp(dirp->d_name, "..") == 0) {    //no current and parent directory
  
                    continue;  
                }  
                ls_dir_r(dirp->d_name);        //only list directories, judged inside the function
  
            }  
        }  
        /* close the directory */  
        if (closedir(dp)) {  
            fprintf(stderr, "Error: can't close the directory %s!/n", path);  
            return -1;  
        }  
        chdir("..");  
    }  
    return 0;  
}  
/* 
    list directories recursively, 
    only directories, nomatter what path you put in 
*/  
int ls_dir_r(char *path)  
{  
    struct stat st;  
    /* open the inode of file */  
    if (lstat(path, &st)) {  
        fprintf(stderr, "Error: %s not exist./n", path);  
        return (-1);  
    }  
    /* only ls directories */  
    if (S_ISDIR(st.st_mode)) {  
        ls_dir(path);  
    }  
}  
/* 
    print the filetype/size/name on the screen 
*/  
int print(char *path)  
{  
    struct stat st;  
    time_t tp;  
    char *filename = NULL;  
    //get current time   
    time(&tp);  
    if (lstat(path, &st)) {  
        fprintf(stderr, "Error: %s can't be opened./n", path);  
        return (-1);  
    }  
    /* get file name */  
    if ((filename = strrchr(path, '/')) != NULL) {  
        filename++;  
    }  
    else {  
        filename = path;  
    }  
    /* judge whether to list the file */  
    if ((S_ISDIR(st.st_mode)|| S_ISREG(st.st_mode))    //only directories and normal files
  
        && (lflag == 0 || (lflag == 1 && (st.st_size >= lower_size)))         //the min size
  
        && (hflag == 0 || (hflag == 1 && (st.st_size <= upper_size)))     //the max size
  
        && (mflag == 0 || (mflag == 1 && ((tp - st.st_mtime) <= modified_time * 24 * 60 * 60)))    //modified time
  
        && (aflag == 1 || (aflag == 0 && filename[0] != '.'))    //file with a '.' infront
  
        ) {  
        printf("%s/t%10ld/t%s/n", (S_ISDIR(st.st_mode) ? "DIR": "FILE"), st.st_size, filename);  
    }  
    return 0;  
}  
/* 
    The main function 
*/  
int main(int argc, char *argv[])  
{  
    getoptions(argc, argv);  
    ls(argv[optind]);  
    return 0;  
}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ls 应用程序 linux