与ls命令输出匹配

时间:2018-10-31 17:55:09

标签: c ls

我正在尝试编写ls命令。我有以下功能可以打印每个文件名:

int ft_list(const char *filename)
{
    DIR *dirp;
    struct dirent *dir;

    if (!(dirp = opendir(filename)))
        return (-1);
    while ((dir = readdir(dirp)))
    {
        if (dir->d_name[0] != '.')
            ft_putendl(dir->d_name);
    }
    closedir(dirp);
    return (0);
}

ls命令将文件组织成适合屏幕宽度的列。我已经读过它,并且我认为它使用了ioctl标准库函数,但是我找不到任何细节。我到底该怎么做?

1 个答案:

答案 0 :(得分:2)

为了将文件排列成列,您需要确定终端窗口的当前宽度。在许多类似Unix的系统(包括Linux和OS X)上,实际上可以使用ioctl选择器来使用TIOCGWINSZ来获取该信息。

这正是ls所做的(在支持ioctl请求的系统上),一旦确定标准输出是终端(除非使用{{1 }}标志)。如果无法确定端子宽度,则使用80。

这是如何获取信息的快速示例。 (在Linux系统上,您可能可以通过键入-1来找到详细信息。)

为简单起见,以下代码假定man tty_ioctl是文件描述符1。回想起来,stdout会更好。如果要检查任意打开的文件,则需要使用FILE_STDOUT来获取fileno的fd编号。

FILE*

自编写上述示例以来,我一直跟踪/* This must come before any include, in order to see the * declarations of Posix functions which are not in standard C */ #define _XOPEN_SOURCE 700 #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/ioctl.h> /* If stdout is a terminal and it is possible to find out how many * columns its window has, return that number. Otherwise, return -1 */ int window_get_columns(void) { struct winsize sizes; int cols = -1; if (isatty(1)) { /* Only try this if stdout is a terminal */ int status = ioctl(1, TIOCGWINSZ, &sizes); if (status == 0) { cols = sizes.ws_col; } } return cols; } /* Example usage */ /* Print a line consisting of 'len' copies of the character 'ch' */ void print_row(int len, int ch) { for (int i = 0; i < len; ++i) putchar(ch); putchar('\n'); } int main(int argc, char* argv[]) { /* Print the first argument centred in the terminal window, * if standard output is a terminal */ if (argc <= 1) return 1; /* No argument, nothing to do */ int width = window_get_columns(); /* If we can't figure out the width of the screen, just use the * width of the string */ int arglen = strlen(argv[1]); if (width < 0) width = arglen; int indent = (width - arglen) / 2; print_row(width - 1, '-'); printf("%*s\n", indent + arglen, argv[1]); print_row(width - 1, '-'); return 0; } 的Gnu实现的来源; here

会显示它(稍微更谨慎)对ls的调用