问题
As a part of an assignment from one of my classes, I have to write a program in C to duplicate the results of the ls -al command. I have read up on the necessary materials but I am still not getting the right output. Here is my code so far, its only supposed to print out the file size and the file name, but the file sizes its printing are not correct.
Code:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
int main(int argc, char* argv[])
{
DIR *mydir;
struct dirent *myfile;
struct stat mystat;
mydir = opendir(argv[1]);
while((myfile = readdir(mydir)) != NULL)
{
stat(myfile->d_name, &mystat);
printf("%d",mystat.st_size);
printf(" %s\n", myfile->d_name);
}
closedir(mydir);
}
These are my results after executing the code:
[root@localhost ~]# ./a.out Downloads
4096 ..
4096 hw22.c
4096 ankur.txt
4096 .
4096 destination.txt
Here are the correct sizes:
[root@localhost ~]# ls -al Downloads
total 20
drwxr-xr-x. 2 root root 4096 Nov 26 01:35 .
dr-xr-x---. 24 root root 4096 Nov 26 01:29 ..
-rw-r--r--. 1 root root 27 Nov 21 06:32 ankur.txt
-rw-r--r--. 1 root root 38 Nov 21 06:50 destination.txt
-rw-r--r--. 1 root root 1139 Nov 25 23:38 hw22.c
Can anyone please point out my mistake.
Thanks,
Ankur
回答1:
myfile->d_name
is the file name not the path, so you need to append the file name to the directory "Downloads/file.txt"
first, if it's is not the working directory:
char buf[512];
while((myfile = readdir(mydir)) != NULL)
{
sprintf(buf, "%s/%s", argv[1], myfile->d_name);
stat(buf, &mystat);
....
As to why it prints 4096
that is the size of the links .
and ..
from the last call to stat()
.
Note: you should allocate a buffer large enough to hold the directory name, the file name the NULL
byte and the separator, something like this
strlen(argv[1]) + NAME_MAX + 2;
回答2:
This is the final code I got to work for anyone interested. It prints the correct file sizes. Credit goes to asker and mux for answering, just putting the code together. Input I got this to work for is "./main ." .
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
int main(int argc, char* argv[])
{
DIR *mydir;
struct dirent *myfile;
struct stat mystat;
char buf[512];
mydir = opendir(argv[1]);
while((myfile = readdir(mydir)) != NULL)
{
sprintf(buf, "%s/%s", argv[1], myfile->d_name);
stat(buf, &mystat);
printf("%zu",mystat.st_size);
printf(" %s\n", myfile->d_name);
}
closedir(mydir);
}
回答3:
I believe you'll observe that if you ./a.out .
you will get the behaviour you expect.
You have a slightly subtle bug, observable if you examine the return code of your call to stat(2)
.
The fundamental mistake: the dirent
s returned by readdir(2)
(the myfile
in your code) will have a d_name
relative to mydir
. Your code will stat
..
first, succeed, and so mystat
will contain valid data for ..
, then all subsequent calls to stat(2)
will fail, returning -1
, which you do not check for, so mystat
will not be modified, and you will print the st_size
for the old value, i.e. that of ..
.
回答4:
The trouble is that when you stat("ankur.txt", &mystat)
, you are not working on the file "Downloads/ankur.txt"
. Most likely, the stat()
is failing; alternatively, it is reporting on a different file.
Consequently, you need to look at whether your system supports fstatat() — new in POSIX 2008 — or arrange to prefix the name of the file with name of the directory.
回答5:
or maybe just system("ls -al") will also work!
来源:https://stackoverflow.com/questions/13554150/implementing-the-ls-al-command-in-c