在*nix系统下,ls命令都是一个很重要的命令,用于某一文件夹中的文件列表,这个命令实现起来其实也十分简单,今天闲来无事,就在Mac上粗略的写写代码。
文件结构
不关注内部细节,ls的主要实现应该包括两个部分,一部分是参数解析,一部分是输出文件列表,所以我的项目文件结构如下所示:
main:程序入口点,调用输出列表函数
fileinfo:ls命令输出行model
parsecmd:该文件主要是参数解析部分,由于只是粗略的写写,并没有做什么检查,也只实现了ls中的-a和-l选项
dirhandler:该文件主要用于读取文件目录列表和文件相关信息。
main函数
首先来看看main函数中的代码,如下所示:
int main(int argc, const char * argv[])
{
char* args = NULL;
int argsCount = ParseCmds(argc, argv, args);
int paths = argc - 1 - argsCount;
if(paths == 0)
showFilesWithArgs(".", args);
else
for(int i = argsCount + 1; i != argc; ++i)
{
if(paths > 1)
printf("%s:\n", argv[i]);
showFilesWithArgs(argv[i], args);
}
return 0;
}
首先,解析参数,结束之后,如果发现用户没有指定目录,则将目录设置为当前目录,否则循环输出每个目录的信息。
命令行解析
由于只是粗略的解析一下,所以命令行解析也只是简单的将命令字符分离出来,代码如下所示:
int ParseCmds(int argc, const char* argv[], char*& args)
{
clean(args);
args = (char*)malloc(sizeof(char) * ARGU_LEN);
memset(args, 0, sizeof(char) * ARGU_LEN);
int cmd_index = 0, argsCount = 0;
for(int i = 1; i != argc; ++i)
{
const char* strp = *(argv + i);
if((*strp) != '-')
break ;
++argsCount;
size_t arglen = strlen(strp);
for(int j = 1; j != arglen; ++j)
args[cmd_index++] = *(strp + j);
}
return argsCount;
}
首先清空参数数组,然后为参数数组分配足够的空间,命令行都是以「-」开头,所以如果不是以该字符开头的命令字符串就不是命令选项了,而应该是目录,就是说命令已经解析完毕。否则将字符一个一个的存到args数组当中。
输出结构字段
fileinfo包含ls输出的各个字段,如下所示:
typedef struct FileInfo
{