简体   繁体   English

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

[英]How to implement unix ls -s command in C?

I have to write a program in C which returns file size in blocks just like ls -s command. 我必须在C中编写一个程序,它以块的形式返回文件大小,就像ls -s命令一样。 Please help. 请帮忙。

I tried using stat() function (st_blksize)...And I am unable to implement it. 我尝试使用stat()函数(st_blksize)......我无法实现它。

My code looks like this 我的代码看起来像这样

#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);
}

It is giving error buf size is not declared. 它是给出错误buf大小未声明。 Don't know what is the problem. 不知道是什么问题。

Addition 加成

Thanks for the correction. 谢谢你的纠正。 I included the <sys/stat.h> header file. 我包含了<sys/stat.h>头文件。 Now it is giving a warning: 现在它发出警告:

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

I am new to C so can't make out what should be the possible solution. 我是C的新手,所以无法弄清楚应该是什么样的解决方案。

You need to include the correct header: 您需要包含正确的标头:

#incude <sys/stat.h>

That declares the structure and associated functions. 这声明了结构和相关的功能。

Note that stat() returns zero on success, so your test needs changing (and, as @jsmchmier pointed out in a comment, the call to stat should probably use dirp->d_name rather than the string literal "." ). 请注意, stat()在成功时返回零,因此您的测试需要更改(并且,正如@jsmchmier在注释中指出的那样,对stat的调用应该使用dirp->d_name而不是字符串文字"." )。 Also, st_blksize is the size of the disk blocks, not the size of the file - that is st_size (measured in bytes). 此外, st_blksize是磁盘块的大小,而不是文件的大小 - 即st_size (以字节为单位)。

POSIX says: POSIX说:

off_t st_size For regular files, the file size in bytes. off_t st_size对于常规文件,文件大小以字节为单位。 For symbolic links, the length in bytes of the pathname contained in the symbolic link. 对于符号链接,符号链接中包含的路径名的长度(以字节为单位)。

blksize_t st_blksize A file system-specific preferred I/O block size for this object. blksize_t st_blksize此对象的特定于文件系统的首选I / O块大小。 In some file system types, this may vary from file to file. 在某些文件系统类型中,这可能因文件而异。

blkcnt_t st_blocks Number of blocks allocated for this object. blkcnt_t st_blocks为此对象分配的块数。

Note that old (very old) versions of Unix did not support st_blksize or st_blocks . 请注意,旧的(非常旧的)Unix版本不支持st_blksizest_blocks I expect most current versions do. 我希望大多数现有版本都可以。


Now it is giving a warning..warning: format '%d' expects type 'int', but argument 2 has type '__blksize_t' 现在它发出警告..警告:格式'%d'需要类型'int',但参数2的类型为'__blksize_t'

The chances are that __blksize_t is an unisgned integer type similar to size_t . __blksize_t可能__blksize_t是一个类似于size_t的unisgned整数类型。 I'd probably use a simple cast: 我可能会使用一个简单的演员:

printf("Block size = %d\n", (int)buf.st_blksize);

Alternatively, if you have C99 available, you could use the facilities from <inttypes.h> to use a bigger size: 或者,如果您有C99可用,您可以使用<inttypes.h>来使用更大的尺寸:

printf("Block size = %" PRIu64 "\n", (uint64_t)buf.st_blksize);

In practice, this is overkill; 在实践中,这是过度的; the block size is unlikely to exceed 2 GB this decade, so int is likely to be sufficient for the foreseeable future. 在这十年中,块大小不太可能超过2 GB,因此在可预见的未来, int可能已足够。

Open the file, and stat/fstat it. 打开文件,然后stat / fstat。 The struct field st_blocks should contain the information you want. struct字段st_blocks应包含所需的信息。 If you're dealing with a directory, use opendir, readdir, closedir (posix)... Just pointers to start your work. 如果你正在处理一个目录,请使用opendir,readdir,closedir(posix)......只是指点开始你的工作。

EDIT 编辑

Add unistd.h and sys/stat.h. 添加unistd.h和sys / stat.h。 Then remember that stat return 0 on success, so 然后记住,stat成功返回0,所以

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

and I've changed "." 我改变了“。” to the name of the "element", which is what you wanted, I suppose. 以为“元素”的名称,这是你想要的,我想。 Another change is to use st_blocks and not st_blksize, which says how big is each block (eg 1024 or 4096 or...), and -s returns the size in number of blocks, not the size of a block. 另一个变化是使用st_blocks而不是st_blksize,它表示每个块有多大(例如1024或4096或......),-s返回块数的大小,而不是块的大小。

The fragment of code is of course incomplete: if you pass an argument, dp is not initialized and even dp == NULL can fail, you shoud have nullified it before: 代码片段当然是不完整的:如果你传递一个参数,dp没有被初始化,甚至dp == NULL都会失败,你应该在之前使它无效:

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

From man 2 stat on my Mac OS X box: 来自我的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);

Note the #include <sys/stat.h> which you have not done. 注意你还没有完成的#include <sys/stat.h> No doubt the actual layout of struct stat is defined in there, which is what your compiler is complaining about. 毫无疑问, struct stat的实际布局是在那里定义的,这是你的编译器所抱怨的。

This is one aspect of the man pages which is not always discussed with beginners but is very useful indeed: the whole unix API is documented in them. 这是手册页的一个方面,并不总是与初学者讨论,但确实非常有用:整个unix API都记录在其中。 Oh, it is not always the easiest place to find a function when you know what it should do but don't know what it is called, but all the answers are there. 哦,当你知道它应该做什么但却不知道它叫什么时,找到一个函数并不总是最简单的地方,但所有答案都在那里。

Careful, one bug in your code is that dp points to garbage and is only initialised if argc is less than 2, but you still try to use it in your while loop and you also try to closedir it. 小心,你的代码中的一个错误是dp指向垃圾,只有当argc小于2时才会初始化,但你仍然尝试在你的while循环中使用它,你也尝试closedir它。 If you invoke your application with any arguments at all, it will probably crash. 如果您使用任何参数调用您的应用程序,它可能会崩溃。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM