2015-06-18 2 views
-1

Я пытаюсь перечислить только файлы с установленным битом execute (+ x). Мой код, кажется, перечисляет все файлы. Кажется, он также перечисляет каталог и указанный выше каталог, который мне не нужен. Пример:Перечисление исполняемых файлов в C

.. 
should_not_be_executable.sh 
. 

Есть ли способ фильтровать '..' и '.' без strstr()? Вот мой код

#include <stdio.h> 
#include <sys/types.h> 
#include <dirent.h> 
#include <sys/stat.h> 
#include <unistd.h> 


int 
main (void) 
{ 
DIR *dp; 
struct dirent *ep; 

dp = opendir ("/tmp/hi"); 
if (dp != NULL) 
{ 
    while (ep = readdir (dp)) 
    { 
    struct stat sb; 
    if ((stat(ep->d_name, &sb) >= 0) && (sb.st_mode > 0) && (S_IEXEC & sb.st_mode)); 
        puts(ep->d_name); 
     } 
    (void) closedir (dp); 
} 
else 
    perror ("Couldn't open the directory"); 
return 0; 
} 

Заранее спасибо

+0

не думаю. См. [Readdir] (http://pubs.opengroup.org/onlinepubs/7908799/xsh/readdir.html) – Dinesh

+0

ОК - но есть идеи, почему в моем коде также отображаются неисполняемые файлы? – user3526827

+2

У вас есть опечатка - бродячая ';' в конце вашей строки 'if'. Это означает, что 'if' не имеет тела, а строка' puts' выполняется для каждой итерации цикла. –

ответ

1

ep->d_name содержит только относительный путь к записи каталога. Таким образом, вы должны изменить рабочий каталог текущего в /tmp/hi перед вызовом stat(2)

if (chdir("/bin") != 0) 
{ 
    perror("chdir()"); 
    exit(EXIT_FAILURE); 
} 

/* ... */ 

if (stat(ep->d_name, &sb) == -1) 
{ 
    perror("stat()"); 
    exit(EXIT_FAILURE); 
} 

Как отмечалось в комментариях @ Андрей Medico, удалите этот дополнительный ; в конце вашей if линии, чтобы избежать ненужной печати этой puts() линии.

readdir() возвращает NULL указатель, когда он достигает в конце каталога, так что вы должны переписать время цикла следующим образом для того, чтобы подавить предупреждения компилятора:

while (NULL != (ep = readdir(dp))) 
{ 
    /* loop */ 
} 

Для того, чтобы избежать печати . и .. используйте if состояние, как это в while теле:

if ((strcmp(ep->d_name, ".") == 0) || (strcmp(ep->d_name, "..") == 0)) 
    continue; 

if ((stat(ep->d_name, &sb) >= 0) && (sb.st_mode > 0) && (S_IEXEC & sb.st_mode)) 
    if (!S_ISDIR(sb.st_mode)) 
      puts(ep->d_name); 

Кроме того, вы можете использовать S_ISDIR(m), чтобы узнать, является ли текущая запись каталогом и не следует ее печатать.