Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 打印行状树命令_C_Linux - Fatal编程技术网

C 打印行状树命令

C 打印行状树命令,c,linux,C,Linux,我正在努力学习C语言编程来完成工作中的一项任务,我给自己设置了一个小项目,其中包括读取一个文件树,包括所有子目录,以获取每个文件的信息 我无法解决的问题是,如何在打印所有目录时像真正的tree命令那样划线 这是我的示例代码: enum { doSkip, isFile, isDir } testDir(char *path, char *name) { struct stat st_buf; if (strcmp(name, ".") == 0 || str

我正在努力学习C语言编程来完成工作中的一项任务,我给自己设置了一个小项目,其中包括读取一个文件树,包括所有子目录,以获取每个文件的信息

我无法解决的问题是,如何在打印所有目录时像真正的tree命令那样划线

这是我的示例代码:

enum { doSkip, isFile, isDir } testDir(char *path, char *name)
{ 
     struct stat st_buf;        
     if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
         return doSkip;
     }   
     stat(path, &st_buf);
     if (S_ISDIR(st_buf.st_mode))
         return isDir;
     return isFile;
}

void list(const char *path, int indentlevel)
{
     DIR *dirp = opendir(path);
     struct dirent *dentry;
     char buf[1024];
     if (!dirp) {
      printf("%*sNo access\n",indentlevel,"");
      return;
     }

     while ((dentry = readdir(dirp)) != NULL) {

        sprintf(buf,"%s/%s", path, dentry->d_name);
        switch (testDir(buf,dentry->d_name)) {
        case doSkip:
           /* do nothing */
           break;
        case isDir:
           printf("%*s%s:\n",indentlevel,"",dentry->d_name);
           list(buf,indentlevel+4);
           break;
        case isFile:
           printf("%*s%s\n",indentlevel,"",dentry->d_name);
           break;
        }
     }
     closedir(dirp);
}

int main()
{
     list(".", 0);
     return 0;
}
请给我一些想法

list(buf,indentlevel+4);
您应该将其更改为
列表(buf,indentlevel+1)
,因为您只上一级。通过这种方式,您可以跟踪目录级别。添加另一个函数以添加额外的空格。请参见下面的示例:

void space(int level, int file)
{
    int i;
    for (i = 0; i < level + 1; i++)
        printf("\x0b3   "); // add the '│' character
    if (file) 
        printf("\x0c3\x0c4  "); // add  '├' and '─' characters
}

void list(const char *path, int indentlevel)
{
    DIR *dirp = opendir(path);
    struct dirent *dentry;
    char buf[1024];
    if (!dirp)
    {
        printf("%*sNo access\n",indentlevel,"");
        return;
    }

    int i;
    while ((dentry = readdir(dirp)) != NULL)
    {
        sprintf(buf,"%s/%s", path, dentry->d_name);
        switch (testDir(buf,dentry->d_name))
        {
        case doSkip:
            break;
        case isDir:
            space(indentlevel, 1);
            putchar('\n');
            space(indentlevel, 0);
            printf("[ %s ]\n",dentry->d_name);
            list(buf,indentlevel+1);
            break;

        case isFile:
            space(indentlevel-1, 1);
            printf("%s\n",dentry->d_name);
            break;
        }
    }

    closedir(dirp);
}
void空格(int级别,int文件)
{
int i;
对于(i=0;id_名称);
开关(testDir(buf,dentry->d_name))
{
多斯基普案:
打破
案例isDir:
空间(1级);
putchar('\n');
空间(缩进级别,0);
printf(“[%s]\n”,dentry->d_name);
列表(buf,缩进级别+1);
打破
案例文件:
空间(1级,1级);
printf(“%s\n”,dentry->d_name);
打破
}
}
closedir(dirp);
}
这是一个更复杂的版本,它将数据存储在缓冲区中,因此它可以找到文件夹中的最后一个子项,并为最后一项绘制正确的“方形边缘”字符。它仍然打印一些额外的垂直线,这需要注意

//store directory information
typedef struct TT_dir
{
    char* name;
    int isdir;
    int level;
    int islast;
} T_dir;

//vector for holding lines of data
typedef struct TT_vector
{
    T_dir *data;
    int capacity;
    int size;
} T_vector;

void vector_add(T_vector *pvec, char *buf, int isdir, int level)
{
    if (pvec->size == pvec->capacity)
    {
        pvec->capacity += 16;
        pvec->data = realloc(pvec->data, pvec->capacity * sizeof(T_dir));
    }

    char *duplicate = malloc(strlen(buf) + 1);
    strcpy(duplicate, buf);
    pvec->data[pvec->size].name = duplicate;
    pvec->data[pvec->size].isdir = isdir;
    pvec->data[pvec->size].level = level;
    pvec->data[pvec->size].islast = 0;
    pvec->size++;
}

void list(const char *path, int level, T_vector *pvec)
{
    DIR *dirp = opendir(path);
    struct dirent *dentry;
    char buf[4096];
    if (!dirp)
    {
        printf("%*sNo access\n", level, "");
        return;
    }

    int haschildren = 0;
    while ((dentry = readdir(dirp)) != NULL)
    {
        sprintf(buf, "%s/%s", path, dentry->d_name);
        switch (testDir(buf, dentry->d_name))
        {
        case doSkip:
            break;
        case isDir:
            //show progress:
            printf(".");

            //add directory info to vector array
            vector_add(pvec, dentry->d_name, 1, level);

            //next dir...
            list(buf, level + 1, pvec);
            haschildren = 1;
            break;

        case isFile:
            //add directory info to vector array
            vector_add(pvec, dentry->d_name, 0, level);
            haschildren = 1;
            break;
        }
    }

    //needs this information for drawing the correct character
    if (haschildren)
        pvec->data[pvec->size - 1].islast = 1;

    closedir(dirp);
}

int main()
{
    T_vector vec;
    vec.capacity = 0;
    vec.size = 0;
    vec.data = 0;

    list(".", 0, &vec);
    printf("\n");

    int i, k;
    for (i = 0; i < vec.size; i++)
    {
        if (vec.data[i].isdir)
        {
            for (k = 0; k < vec.data[i].level; k++) printf("\x0b3   ");
            printf("\x0b3\n");

            for (k = 0; k < vec.data[i].level; k++) printf("\x0b3   ");

            printf(vec.data[i].islast ? "\x0c0" : "\x0c3");

            printf("\x0c4  %s:\n", vec.data[i].name);
        }
        else
        {
            for (k = 0; k < vec.data[i].level; k++) printf("\x0b3   ");

            printf(vec.data[i].islast ? "\x0c0" : "\x0c3");

            printf("\x0c4  %s\n", vec.data[i].name);
        }
    }

    return 0;
}
//存储目录信息
类型定义结构TT_目录
{
字符*名称;
国际isdir;
智力水平;
int islast;
}图迪尔;
//用于保存数据行的向量
类型定义结构TT_向量
{
T_dir*数据;
国际能力;
整数大小;
}T_向量;
void vector_add(T_vector*pvec,char*buf,int-isdir,int-level)
{
如果(pvec->size==pvec->capacity)
{
pvec->容量+=16;
pvec->data=realloc(pvec->data,pvec->capacity*sizeof(T_dir));
}
char*duplicate=malloc(strlen(buf)+1);
strcpy(副本,基本单位);
pvec->数据[pvec->大小].name=重复;
pvec->数据[pvec->大小].isdir=isdir;
pvec->数据[pvec->大小].level=level;
pvec->数据[pvec->大小].islast=0;
pvec->size++;
}
无效列表(常量字符*路径,整数级,T_向量*pvec)
{
DIR*dirp=opendir(路径);
结构方向*dentry;
char-buf[4096];
if(!dirp)
{
printf(“%*sNo访问\n”,级别“”);
回来
}
int haschildren=0;
而((dentry=readdir(dirp))!=NULL)
{
sprintf(buf,“%s/%s”,路径,dentry->d_名称);
开关(testDir(buf,dentry->d_name))
{
多斯基普案:
打破
案例isDir:
//显示进度:
printf(“.”);
//将目录信息添加到向量数组
矢量添加(pvec,dentry->d_名称,1,级别);
//下一个方向。。。
列表(buf,级别+1,pvec);
haschildren=1;
打破
案例文件:
//将目录信息添加到向量数组
矢量添加(pvec,dentry->d_名称,0,级别);
haschildren=1;
打破
}
}
//需要此信息才能绘制正确的字符
如果(有孩子)
pvec->data[pvec->size-1].islast=1;
closedir(dirp);
}
int main()
{
T_向量向量向量;
向量容量=0;
向量大小=0;
向量数据=0;
列表(“.”、0和向量);
printf(“\n”);
int i,k;
对于(i=0;i
您需要了解的是printf不必打印整行。与其他语言中的其他打印函数不同

for(i=0;i<identlevel;i++)
  printf("-");
 printf("[ %s ]\n", dentry->dname);
for(i=0;idname);

这就可以了。

您需要一个缩进级别列表,对于超过一个子目录深度的任何内容都会绘制多个并行分支。我看到的唯一区别是tree命令的输出是排序的。因此,如果你想对结果进行排序,只需将它们放入某种容器中,然后进行排序并打印即可。如果有比排序更多的内容,请告诉我。我如何列出缩进级别@tripleeewell我不认为我需要对这些结果进行排序,我只想像真正的tree命令那样画一条线:(@klaust)帮助您了解出错的情况。