您的位置:首页 > 运维架构 > Linux

使用linux c 实现linux控制台 ls 命令

2016-07-20 13:35 567 查看
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <error.h>
#include <time.h>// ctime()函数

#include <dirent.h>//操作目录
#include <sys/stat.h>//操作文件
#include <pwd.h>// 获取文件所有者
#include <grp.h>

//InfoModeAll -a        InfoModeDetail -l
//显示信息模式
typedef enum _InfoMode { InfoModeBothNo,InfoModeAll,InfoModeDetail,InfoModeBoth} InfoMode;
//目录元素种类(文件、目录)
enum ItemCategory { ItemCategoryDir, ItemCategoryFile };

//显示目录中元素列表
void display_dirItemList(char *path, int isAll);
//显示目录中元素信息
void display_dirItemInfo(char *path, int isAll);

//显示目录信息
void display_singleDirInfo(char *path);
//显示文件信息
void display_singleFileInfo(char *path);
//显示文件名,根据文件路径
void display_fileName(char *path);

//显示文件信息
void display_fileInfo(char *path, InfoMode mode);
//显示目录信息
void display_dirInfo(char *path, InfoMode mode);

//解析命令行参数,返回,显示信息模式
InfoMode AnalyticalParm(int argc, char **arg);
//获取完整路径
void getAbsolutePath(char *path);
//检查path是否为绝对路径,0 不是,是相对路径  1 是绝对路径
int checkPathIsAbsolutePath(char *path);
//获取目录下的文件/目录名称,返回char **(这个变量需要动态释放),以及fileNameCount
void getFileNameListFormDir(char *path,int isAll,char fileNameList[][10],int *fileNameCount);
//打印目录元素的属性
void Demonstrate_attribute(struct stat buf);
//判断元素是文件还是目录
int checkPathIsFile(char *path);

int main(int argc, char **arg) {
/*
argc = 3;
arg[0] = "./my_ls";
arg[1] = "-a";
arg[1] = "-l";
arg[2] = "/home/pengjing/文档/10-文件读写/my_ls/bin/Debug/test/";
//int i;
//for(i=0; i<argc; i++) {
//printf("%s\t",arg[i]);
//}
//printf("\n");
*/

InfoMode mode = AnalyticalParm(argc, arg);
char *path = arg[argc-1];
//判断是否为文件名,还是目录名,当res_index为0时,是目录名,当res_index为.所在的索引时为文件名
getAbsolutePath(path);
//过滤最后一个"/"
if(path[strlen(path)-1] == '/'){
path[strlen(path)-1] = '\0';
}

int isFile = checkPathIsFile(path);
if(isFile == 1) {
display_fileInfo(path,mode);
} else {
display_dirInfo(path,mode);
}

return 0;
}

void display_dirItemList(char *path, int isAll) {
int fileNameCount = 0;
char fileNames[30][10];
getFileNameListFormDir(path,isAll,fileNames,&fileNameCount);
int i;
for(i=0;i<fileNameCount;i++){
printf("%-s\t",fileNames[i]);
}
printf("\n");
}
void display_dirItemInfo(char *path, int isAll) {
int fileNameCount = 0;
char fileNameList[30][10];
char filePathList[30][100];
int i,j;
getFileNameListFormDir(path,isAll,fileNameList,&fileNameCount);
for(i=0; i<fileNameCount; ++i) {
char filePath[90] = {'\0'};
strcpy(filePath,path);
strcat(filePath,"/");
strcat(filePath,fileNameList[i]);
strcpy(filePathList[i],filePath);
}
struct stat _stat;
for(i=0; i<fileNameCount; i++) {
//bzero(_stat,sizeof(struct stat));
//printf("%s\n",filePathList[i]);
// /home/pengjing/document/10-文件读写/my_ls/bin/Debug/test/file1
// char *myPath = "/home/pengjing/document/10-文件读写/my_ls/bin/Debug/test/file1";
int res_lstat = lstat(filePathList[i],&_stat);
if(res_lstat == -1) {
perror("lstat");
exit(0);
}
Demonstrate_attribute(_stat);
}
}
void getFileNameListFormDir(char *path,int isAll,char fileNameList[][10],int *fileNameCount) {
struct dirent *diren;
DIR *dir;
*fileNameCount = 0;

//printf("fileNameList size :%ld\n",sizeof(fileNameList));
if((dir = opendir(path)) == NULL) {
perror("opendir");
}
while((diren = readdir(dir)) != NULL) {
char *name = diren->d_name;
if(isAll == 0 && name[0] == '.') {
continue;
}
strcpy(fileNameList[*fileNameCount],name);
(*fileNameCount)++;
}
closedir(dir);
}

//显示文件信息
void display_singleFileInfo(char *path) {
//printf("显示单个文件信息\n");
struct stat _stat;
int res_lstat = lstat(path,&_stat);
if(res_lstat == -1) {
perror("lstat");
exit(0);
}
Demonstrate_attribute(_stat);
}

void display_fileName(char *path){
//printf("显示文件名");
char res[10],*a;
a = rindex(path,'/');
strcpy(res,a);
int i;
for(i=1;i<strlen(res);i++){
res[i-1] = res[i];
}
res[i-1] = '\0';
printf("%s\n",res);
}

//显示文件信息
void display_fileInfo(char *path, InfoMode mode) {
//printf("显示文件的详细信息 mode:%d\n",mode);
//根据显示模式显示内容
switch(mode) {
case InfoModeBothNo: {
//显示目录中元素的名称
display_fileName(path);
break;
}
case InfoModeAll: {
//显示目录中所有元素的名称
display_fileName(path);
break;
}
case InfoModeDetail: {
//显示目录下元素的信息
display_singleFileInfo(path);
break;
}
case InfoModeBoth: {
//显示目录下所有元素的信息
display_singleFileInfo(path);
break;
}
default : {
//mode 错误
printf("mode 错误");
exit(0);
break;
}
}
}
//显示目录信息
void display_dirInfo(char *path, InfoMode mode) {
//printf("显示目录的详细信息 mode:%d\n",mode);
//根据显示模式显示内容
switch(mode) {
case InfoModeBothNo: {
//显示目录中元素的名称
display_dirItemList(path,0);
break;
}
case InfoModeAll: {
//显示目录中所有元素的名称
display_dirItemList(path,1);
break;
}
case InfoModeDetail: {
//显示目录下元素的信息
display_dirItemInfo(path,0);
break;
}
case InfoModeBoth: {
//显示目录下所有元素的信息
display_dirItemInfo(path,1);
break;
}
default : {
//mode 错误
printf("mode 错误");
exit(0);
break;
}
}
}

//解析命令行参数,返回parmCount(参数个数),显示信息模式
InfoMode AnalyticalParm(int argc, char **arg) {
int i;
InfoMode mode = InfoModeBothNo;
for(i = 1 ; i < argc; i++) {
if(arg[i][0] == '-') {
if(arg[i][1] == 'a') {
if(mode == InfoModeDetail) {
mode = InfoModeBoth;
break;
}
mode = InfoModeAll;
} else if(arg[i][1] == 'l') {
if(mode == InfoModeAll) {
mode = InfoModeBoth;
break;
}
mode = InfoModeDetail;
}
}
}
return mode;
}

int checkPathIsAbsolutePath(char *path) {
int res = 0;
if(path[0] == '/' || path[0] == '~') {
res = 1;
}
return res;
}

//获取文件属性并打印
void Demonstrate_attribute(struct stat buf){
char buf_time[32]; //存放时间
struct passwd *psd; //从该结构体中获取文件所有者的用户名
struct group *grp; //从该结构体中获取文件所有者所属组的组名
/*
我们使用最多的属性是st_mode.通过着属性我们可以判断给定的文件是一个普通文件还是一个目录,连接等等.可以使用下面几个宏来判断.
S_ISLNK(st_mode):是否是一个连接
S_ISREG是否是一个常规文件
S_ISDIR是否是一个目录
S_ISCHR是否是一个字符设备
S_ISBLK是否是一个块设备
S_ISFIFO是否是一个FIFO文件
S_ISSOCK是否是一个SOCKET文件

S_IFMT      0170000     文件类型的位遮罩
S_IFSOCK    0140000     socket
S_IFLNK     0120000     符号链接(symbolic link)
S_IFREG     0100000     一般文件
S_IFBLK     0060000     区块装置(block device)
S_IFDIR     0040000     目录
S_IFCHR     0020000     字符装置(character device)
S_IFIFO     0010000     先进先出(fifo)
S_ISUID     0004000     文件的(set user-id on execution)位
S_ISGID     0002000     文件的(set group-id on execution)位
S_ISVTX     0001000     文件的sticky位
S_IRWXU     00700       文件所有者的遮罩值(即所有权限值)
S_IRUSR     00400       文件所有者具可读取权限
S_IWUSR     00200       文件所有者具可写入权限
S_IXUSR     00100       文件所有者具可执行权限
S_IRWXG     00070       用户组的遮罩值(即所有权限值)
S_IRGRP     00040       用户组具可读取权限
S_IWGRP     00020       用户组具可写入权限
S_IXGRP     00010       用户组具可执行权限
S_IRWXO     00007       其他用户的遮罩值(即所有权限值)
S_IROTH     00004       其他用户具可读取权限
S_IWOTH     00002       其他用户具可写入权限
S_IXOTH     00001       其他用户具可执行权限
*/
//获取并打印文件类型
if (S_ISLNK(buf.st_mode)){ //判断是否为符号链接
printf("l");
}else if (S_ISREG(buf.st_mode)){ //判断是否为文件
printf("-");
}else if (S_ISDIR(buf.st_mode)){ //判断是否为目录
printf("d");
}else if (S_ISCHR(buf.st_mode)){ //判断是否为字符设备文件
printf("c");
}else if (S_ISBLK(buf.st_mode)){ //判断是否为块设备文件
printf("b");
}else if (S_ISFIFO(buf.st_mode)){ //判断是否为先进先出的FIFO
printf("f");
}else if (S_ISSOCK(buf.st_mode)){ //判断是否为socket
printf("s");
}
//获取并打印文件所有者的权限
//按位与结果作为条件判断,应当判断其与结果为0还是非0数值  当前比较的是buf.st_mode在用户读权限的位与S_IRUSR是否相等
if (buf.st_mode & S_IRUSR){
printf("r");
}else{
printf("-");
}
if (buf.st_mode & S_IWUSR){
printf("w");
}else{
printf("-");
}
if (buf.st_mode & S_IXUSR){
printf("x");
}else{
printf("-");
}
//获取并打印与文件所有者同组的用户对该文件的操作权限
if(buf.st_mode & S_IRGRP){
printf("r");
}else{
printf("-");
}
if(buf.st_mode & S_IWGRP){
printf("w");
}else{
printf("-");
}
if(buf.st_mode & S_IXGRP){
printf("x");
}else{
printf("-");
}
//获取并打印其它用户的对该文件的操作权限
if (buf.st_mode & S_IROTH){
printf("r");
}else{
printf("-");
}
if (buf.st_mode & S_IWOTH){
printf("w");
}else{
printf("-");
}
if (buf.st_mode & S_IXOTH){
printf("x");
}else{
printf("-");
}
printf(" ");
//根据uid与gid获取文件所有者的用户名与组名
psd = getpwuid(buf.st_uid);
grp = getgrgid(buf.st_gid);
printf("%4d ",buf.st_nlink); //打印文件的链接数(该文件硬链接数目)
printf("%-9s", psd->pw_name); //打印文件拥有者
printf("%-8s", grp->gr_name); //打印文件所属用户组
printf("%6d",(int)buf.st_size); // 打印文件的大小
char *wo = ctime(&buf.st_mtime);
strcpy(buf_time, ctime(&buf.st_mtime));
buf_time[strlen(buf_time) - 1] = '\0'; // 去掉换行符
printf(" %s\n", buf_time); // 打印文件的时间信息
}

int checkPathIsFile(char *path){
int res = 0;
struct stat _stat;
int res_lstat = lstat(path,&_stat);
if(res_lstat == -1){
perror("lstat");
exit(0);
}
if(S_ISREG(_stat.st_mode)){ //判断是否为文件
res = 1;
}
return res;
}

void getAbsolutePath(char *path){
//组建绝对路径
char absPath[100];
int isAbsolutePath = checkPathIsAbsolutePath(path);
if(isAbsolutePath == 1) {
//absPath = (char *)malloc(sizeof(char) * strlen(path));
strcpy(absPath,path);
} else {
if(getcwd(absPath,200) == NULL) {
perror("获取当前工作目录失败");
}
strcat(absPath,"/");
strcat(absPath,path);
//printf("absPath:%s\n",absPath);
}
path = absPath;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Linux c linux c ls