文件导入

linux下ls的c语言实现 v0.2

[c]

/*
Filename: list.c
Author: guozan @SCS-BUPT
Mail: zendo.guo@gmail.com
Date: 2010/4/6
Desciptions: a program similar with linux's ls, with
-a : list all, include ones with . infront
-r : recursively ls
-l : the minimum size of file to list
-h : the maximum size of file to list
-m : the last modified time till now, in day

More: v0.2 : modified the morning about 0:18 2010/4/7
by guozan
print more beautiful, such as print the absolute path, and align better
*/

#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;
char temp[100]; //used to store the absolute path
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);
// get the path
getcwd(temp, 100);
printf("/n%s:/n****************************************/n", temp);
/* 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;
}
lsdir_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 lsdir_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/t": "FILE"), st.st_size, filename);
}

return 0;
}
/*
The main function
*/
int main(int argc, char *argv[])
{
getoptions(argc, argv);
ls(argv[optind]);
return 0;
}
[/c]

评论