问题
I'm trying to list up my local file-system recursively using dirent.h
. In order to prevent from following sym-links, I'm using the sys/stat.h
header. In the following you can find my SSCCE program.
/**
* coding: utf-8
*
* Copyright (C) 2013, Niklas Rosenstein
*
* listdir.c - List up directories and file-content recursively.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
void list_dir(const char* directory_name) {
DIR* directory_handle = opendir(directory_name);
if (directory_handle == NULL) {
fprintf(stderr, "Could not open directory %s.\n", directory_name);
return;
}
char buffer[1024];
struct dirent* dentry;
int directory_name_length = strlen(directory_name);
memcpy(buffer, directory_name, directory_name_length);
buffer[directory_name_length] = '/';
while ((dentry = readdir(directory_handle)) != NULL) {
char* name = dentry->d_name;
int length = strlen(name);
// Skip the dotted elements.
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) continue;
// Concatenate the directory name with the element name.
memcpy(buffer + directory_name_length + 1, name, length);
buffer[directory_name_length + 1 + length] = 0;
printf("%s\n", buffer);
// Proceed recursively if the element is a directory.
struct stat s;
if (stat(buffer, &s) != 0) {
fprintf(stderr, "WARNING: stat() failed on %s\n", buffer);
continue;
}
mode_t mode = s.st_mode;
if (mode & S_IFDIR && !(mode & S_IFLNK)) {
list_dir(buffer);
}
}
closedir(directory_handle);
}
int main(int argc, char** argv) {
if (argc != 2) {
fprintf(stderr, "Expected exactly 2 arguments.\n");
return -1;
}
list_dir(argv[1]);
return 0;
}
I just can't get it to work to detect symbolic links correctly. When it comes accross a symbolic link, linking to it's parent directory, it goes on and on and on. It seems like there are a few folders like this on my system, eg. /usr/bin/X11
:
/usr/bin/X11/
X11/ -> .
This line must not be entirely correct: if (mode & S_IFDIR && !(mode & S_IFLNK)) {
. Is it propabaly an issue with the stat()
function or am I missing something obvious here?
Here's a picture of my terminal after invoking ./listdir /usr/bin/X11
, stopping the program after about a second by pressing ^C
.
回答1:
Try lstat
instead of stat
: the latter, when done on symbolic link, returns information on its target (the final one, which is not a symbolic link).
S_IFDIR
and S_IFLNK
are not supposed to be used as if they were exclusive bit flags. For directory, use S_ISDIR(mode)
; for symbolic link, you'll need no test: lstat
won't report symbolic link as a directory, and that's enough when all you want is to skip symbolic links.
来源:https://stackoverflow.com/questions/14449370/ubuntu-listing-up-files-recursively-detecting-sym-links