功能
- 获取当前工作目录路径并对该目录实现遍历;
- 以列表形式列出当前工作目录下的所有文件(包括子目录),并显示每个文件的属性信息(文件类型、文件权限、文件硬链接数、文件所有者用户名、文件所有者所在组用户名、文件大小、文件最后修改时间)
- 根据命令行参数决定是否显示当前目录本身“.”和上级目录“…”
- 根据命令行参数决定是否显示隐藏文件(文件名以“.”作为开始的文件)
- 根据命令行参数决定是显示符号链接文件本身的属性还是符号链接指向文件的文件属性。
源码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <string.h>
char* join (char *a, char *catb, char *c) {
char *ret;
int i = strlen (a), j = strlen (catb), k = strlen (c), n;
ret = (char*) malloc (sizeof (char) * (i + j + k + 1));
for (n = 0; n < i; n++)
ret[n] = a[n];
for (n = 0; n < j; n++)
ret[i + n] = catb[n];
i += j;
for (n = 0; n < k; n++)
ret[i + n] = c[n];
ret[i + n] = 0;
return ret;
}
void printMode (mode_t mode) {
static char map[3][2] = {"r", "w", "x"};
if (S_ISREG (mode))
printf ("-");
else if (S_ISDIR (mode))
printf ("d");
else if (S_ISCHR (mode))
printf ("c");
else if (S_ISBLK (mode))
printf ("b");
else if (S_ISFIFO (mode))
printf ("f");
else if (S_ISSOCK (mode))
printf ("s");
else if (S_ISLNK (mode))
printf ("l");
else printf ("!");
int n = (int) mode, i, j;
for (i = 8; i > -1;)
for (j = 0; j < 3; j++)
printf ((n >> i--) & 1 == 1 ? map[j] : "-");
}
void printTime (time_t mtime) {
char *s = ctime (&mtime);
int i = 0;
while (s[i] != '\n') i++;
s[i] = 0;
printf ("%s ", s);
}
/* stat list */
typedef struct _statnode {
char name[256];
struct stat st;
struct _statnode *next;
} StatNode;
typedef struct _statList {
int size;
StatNode *head, *tail;
} StatList;
StatList* createStatList () {
StatList *statList = (StatList*) malloc (sizeof (StatList));
bzero (statList, sizeof (StatList));
statList->tail = statList->head = (StatNode*) malloc (sizeof (StatNode));
bzero (statList->tail, sizeof (StatNode));
return statList;
}
StatNode* newStatNode (StatList *statList) {
StatNode *node = (StatNode*) malloc (sizeof (StatNode));
statList->tail->next = node;
statList->tail = node;
statList->size++;
return node;
}
void printStatList (StatList *statList) {
int nNlink = 0, nUserName = 0, nGroupName = 0, nSize = 0, tmp;
StatNode *node = statList->head->next;
char buf[256] = {0};
struct passwd *pw;
struct group *gr;
while (node != NULL) {
sprintf (buf, "%d", node->st.st_nlink);
if ((tmp = strlen (buf)) > nNlink) nNlink = tmp;
pw = getpwuid (node->st.st_uid);
sprintf (buf, "%s", pw->pw_name);
if ((tmp = strlen (buf)) > nUserName) nUserName = tmp;
gr = getgrgid (node->st.st_gid);
sprintf (buf, "%s", gr->gr_name);
if ((tmp = strlen (buf)) > nGroupName) nGroupName = tmp;
sprintf (buf, "%d", node->st.st_size);
if ((tmp = strlen (buf)) > nSize) nSize = tmp;
node = node->next;
}
node = statList->head->next;
sprintf (buf, ". %%%dd %%%ds %%%ds %%%dd ", nNlink, nUserName, nGroupName, nSize);
while (node != NULL) {
printMode (node->st.st_mode);
pw = getpwuid (node->st.st_uid);
gr = getgrgid (node->st.st_gid);
printf (buf, node->st.st_nlink, pw->pw_name, gr->gr_name, node->st.st_size);
printTime (node->st.st_mtime);
printf ("%s\n", node->name);
node = node->next;
}
}
void destroyStatList (StatList *statList) {
if (statList != NULL) {
StatNode *node = statList->head, *next;
while (node != NULL) {
next = node->next;
free (node);
node = next;
}
statList->tail = statList->head = NULL;
statList->size = -1;
free (statList);
}
}
/* main */
void printUsage () {
printf ("usage:\n");
printf (" -h: help\n");
printf (" -a: show all files\n");
printf (" -c: hide current directory and its parent directory\n");
printf (" -l: show symbolic link itself\n");
}
int main(int argc, char **argv) {
int op_a = 0, op_c = 0, op_l = 0;
if (argc > 1) {
int i;
for (i = 1; i < argc; i++) {
if (strcmp (argv[i], "-a") == 0) op_a = 1;
else if (strcmp (argv[i], "-c") == 0) op_c = 1;
else if (strcmp (argv[i], "-l") == 0) op_l = 1;
else {
printUsage ();
return 0;
}
}
}
DIR *cwd;
struct dirent *cdp;
char *cwdPath = getcwd (NULL, 0);
StatList *statList = createStatList();
if ((cwd = opendir (cwdPath)) != NULL) {
while ((cdp = readdir (cwd)) != NULL) {
if (!op_c && (strcmp (cdp->d_name, ".") == 0 || strcmp (cdp->d_name, "..") == 0))
continue;
if (!op_a && cdp->d_name[0] == '.' && cdp->d_name[1] != '.' && strlen (cdp->d_name) > 1)
continue;
char *fullpath = join (cwdPath, "/", cdp->d_name);
StatNode *node = newStatNode (statList);
strcpy (node->name, cdp->d_name);
if (op_l)
lstat (fullpath, &node->st);
else
stat (fullpath, &node->st);
if (S_ISLNK (node->st.st_mode)) {
int n = strlen (fullpath);
if ((n = readlink (fullpath, fullpath, n)) != -1) {
fullpath[n] = 0;
char *tmp = join (cdp->d_name, " -> ", fullpath);
strcpy (node->name, tmp);
free (tmp);
}
}
free (fullpath);
}
printStatList (statList);
}
else printf ("failed to open cwd\n");
destroyStatList (statList);
free (cwd);
}
运行实例