如何在C中实现unix ls -s命令?

时间:2010-06-06 17:55:10

标签: c unix

我必须在C中编写一个程序,它以块的形式返回文件大小,就像ls -s命令一样。 请帮忙。

我尝试使用stat()函数(st_blksize)......我无法实现它。

我的代码看起来像这样

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>

void main(int argc, char **argv)
{
    DIR           *dp;
    struct dirent *dirp;
    struct stat    buf;

    if(argc < 2)
    {
        dp = opendir(".");
    }

    if(dp == NULL)
    {
        perror("Cannot open directory ");
        exit(2);
    }

    while ((dirp = readdir(dp)) != NULL)
    {
        printf("%s\n", dirp->d_name);
        if (stat(".", &buf))
        printf("%d ", buf.st_blksize);
    }

    closedir(dp);
    exit(0);
}

给出错误buf大小未声明。不知道是什么问题。

加成

感谢您的纠正。我包含了<sys/stat.h>头文件。现在它发出警告:

warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘__blksize_t’

我是C的新手,所以无法弄清楚应该是什么样的解决方案。

5 个答案:

答案 0 :(得分:5)

您需要包含正确的标题:

#incude <sys/stat.h>

宣告结构和相关功能。

请注意stat()成功时返回零,因此您的测试需要更改(并且,正如@jsmchmier在注释中指出的那样,对stat的调用应该使用dirp->d_name而不是字符串文字{ {1}})。此外,"."是磁盘块的大小,而不是文件的大小 - st_blksize(以字节为单位)。

POSIX说:

  

st_size对于常规文件,文件大小以字节为单位。                           对于符号链接,以字节为单位的长度                           路径名包含在符号链接中。

     

off_t st_size特定于文件系统的首选I / O块大小                           对于这个对象。在某些文件系统类型中,这个                           可能因文件而异。

     

blksize_t st_blksize为此对象分配的块数。

请注意,旧的(非常旧的)Unix版本不支持blkcnt_t st_blocksst_blksize。我希望大多数当前版本都可以。


  

现在它发出警告..警告:格式'%d'需要类型'int',但参数2的类型为'__blksize_t'

st_blocks可能是与__blksize_t类似的未分解整数类型。我可能会使用一个简单的演员:

size_t

或者,如果您有C99可用,则可以使用printf("Block size = %d\n", (int)buf.st_blksize); 中的设施来使用更大的尺寸:

<inttypes.h>

在实践中,这是过度的;这个十年的块大小不太可能超过2 GB,因此在可预见的未来,printf("Block size = %" PRIu64 "\n", (uint64_t)buf.st_blksize); 可能已经足够了。

答案 1 :(得分:1)

打开文件,然后使用stat / fstat。 struct字段st_blocks应包含所需的信息。如果你正在处理一个目录,请使用opendir,readdir,closedir(posix)......只需指点即可开始工作。

修改

添加unistd.h和sys / stat.h。然后记住,stat在成功时返回0,所以

if (stat(dirp->d_name, &buf) == 0)

我改变了。“以为“元素”的名称,这是你想要的,我想。另一个变化是使用st_blocks而不是st_blksize,它表示每个块有多大(例如1024或4096或......),-s返回块数的大小,而不是块的大小。

代码片段当然是不完整的:如果你传递一个参数,dp没有初始化,甚至dp == NULL都可能失败,你应该在之前使它无效:

    DIR           *dp = NULL;
    struct dirent *dirp = NULL;

答案 2 :(得分:1)

从Mac OS X上的man 2 stat框:

NAME
     fstat, fstat64, lstat, lstat64, stat, stat64 -- get file status  

SYNOPSIS  
     #include <sys/stat.h>  

     int
     fstat(int fildes, struct stat *buf);

请注意您尚未完成的#include <sys/stat.h>。毫无疑问,struct stat的实际布局是在那里定义的,这是你的编译器所抱怨的。

这是手册页的一个方面,并不总是与初学者讨论,但非常确实有用:整个unix API都记录在其中。哦,当你知道它应该做什么但却不知道它叫什么时,找到一个函数并不总是最简单的地方,但所有答案都在那里。

答案 3 :(得分:1)

小心,代码中的一个错误是dp指向垃圾,只有在argc小于2时才会初始化,但您仍尝试在while循环中使用它你也尝试closedir它。如果您使用任何参数调用您的应用程序,它可能会崩溃。

答案 4 :(得分:0)

要避免警告,请将行中的%d更改为%ld:printf(“%d”,buf.st_blksize);