- /*
- 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的C语言实现
最新推荐文章于 2023-02-28 20:30:13 发布