2013-07-10 2 views
1

У меня есть функция, чтобы проверить файл существующего:Как проверить, существует ли файл в определенных каталогах?

int file_exists(char *filename) 
{ 
    struct stat buffer; 
    int i = stat(filename, &buffer); 
    if (i == 0) { 
     return 1; 
    } 
    return 0; 
} 

и она отлично работает с полным путем, но я хочу, чтобы проверить, если файл существует в домашней директории пользователя, а если нет - в/и т.д. каталог. Как это сделать?

+3

Последние 4 строки вашего тела функции эквивалентны 'return! I;'. –

+1

@Nips: эта функция возвращает ненулевое значение, если данный путь относится к каталогу вместо обычного файла. Если вы хотите, чтобы он возвращал ненулевое значение, только если путь относится к обычному файлу, вам нужно проверить член 'st_mode'' struct stat'. Например, 'return (stat (filename, & buffer) == 0 && S_ISREG (buffer.st_mode)); –

ответ

2
int 
file_exists(const char *basename) 
{ 
    static const char *dirs[] = { "/etc", "/home/username" }; 
    char buf[MAX_PATH_LENGTH + 1]; 
    size_t i; 
    struct stat dummy; 

    for (i = 0; i < sizeof dirs/sizeof dirs[0]; ++i) { 
     (void)snprintf(buf, sizeof buf, "%s/%s", dirs[i], basename); 
     if (!stat(buf, &dummy)) return 1; 
    } 

    return 0; 
} 

Обратите внимание, что это не получится (то есть поиск неправильного файла), если путь плюс имя файла длиннее, чем символы MAX_PATH_LENGTH. Вы можете проверить возвращаемое значение snprintf, чтобы поймать это.

Если вы хотите избежать поиска каталогов/сокетов/..., Вы можете изменить if линию

if (!stat(buf, &dummy) && S_ISREG(dummy.st_mode)) return 1; 

как указывал Адам Розенфельд. В этом случае вы, вероятно, захотите переименовать dummy в нечто более подходящее (возможно, sb).

0

Используйте значение errno, оно будет ENOENT, если файла не существует.

#include <errno.h> 
int file_exists(char *filename) 
{ 
    struct stat buffer; 
    int i = stat(filename, &buffer); 
    if (i == 0) { 
     return 1; 
    } 
    if (errno == ENOENT) 
     printf("%s : file not found\n", buffer); 
    return 0; 
} 

Для вашей проблемы: использовать chdir, если вы не хотите, чтобы сцепить каталог с вашим именем.

0

только принять «имя файла» в качестве входных данных, а затем использовать strcat, чтобы создать полное имя - что-то, как показано ниже:

int file_exists(char *filename) 
{ 
    struct stat buffer; 
    char fullpath[50], *path; 
    path = "/home/Nips/" 
    if ((strlen(path) + strlen(filename)) >= 50) { 
     printf("filename too long!\n"); 
     return 0; 
    } 
    strcpy(fullpath, path); 
    strcat(fullpath, filename); 
    if (stat(fullpath, &buffer) == 0) { 
     return 1; 
    } 
    if (errno == ENOENT) { 
     path = "/etc/"; 
     strcpy(fullpath, path); 
     strcat(fullpath, filename); 
     if (stat(fullpath, &buffer) == 0) { 
      return 1; 
     } 
     if (errno == ENOENT) { 
      printf("File not found!\n"); 
      return 0; 
     } 
    } 
    printf("Error finding File!\n"); 
    return 0; 
} 

Примечание: Код не испытывается, это просто чтобы дать вам подсказку. Выполняйте правильную проверку работоспособности во время внедрения. Надеюсь, это даст вам некоторую идею!

+0

Хорошо, я обновил свой ответ с проверкой переполнения имени файла, теперь это безопасно. И так как мы знаем размер заранее, так что не обязательно использовать strncat(). Благодаря! –

+2

Использование 'strcat()' для инициализации 'fullpath' неверно. 'fullpath' не инициализируется вообще, прежде чем' strcat() 'вызывается в первый раз, поэтому поведение не определено. Вместо этого используйте 'strcpy()' (или лучше, 'strncpy()') при инициализации 'fullpath' с помощью пути, затем используйте' strcat() '(или' strncat() ') только для добавления' filename' в ' fullpath'. –

+0

Хорошо, я предлагаю вам сделать полный путь 0, а затем использовать strcat(), но, я совсем не согласен с вами в том, что strcat() здесь небезопасен. Мы заранее знаем размер, мы знаем, что делаем. Поскольку, каждый хочет strncat(), поэтому я внес изменения. –

0

Всегда указывайте полный адрес по вашему пути или ./ в текущем каталоге.

Также, в соответствии с этим similar question, доступ (путь, режим) функция делает то, что вам нужно. Используйте его вместо этого. Он возвращает 0 при успехе, или -1 в случае отказа. Поскольку access() выполняет именно то, что вам нужно, вам не нужно его повторно выполнять.

Примечание, наиболее распространенные режимы являются следующие:

F_OK, для проверки, если файл существует.

R_OK, для чтения.

W_OK, для записи.

X_OK, для чтения, записи и выполнения разрешений.

Кроме того, если, например, вам нужно проверить, как чтение и разрешение письма, вы можете иметь побитового или между R_OK и W_OK (или даже между каждыми тремя R_OK, W_OK или X_OK)

Для получения дополнительной информации , введите человек доступа на свой терминал или перейдите по ссылке выше.

Опасайтесь: access() является частью библиотеки unistd.h, то есть стандарта POSIX. Если вам нужно его использовать в других системах, вам может потребоваться включить разные библиотеки.

+0

Я думаю, что вопрос в том, как проверить разные пути (как составить пути). –

+0

Да, ты прав. Может быть, я могу опубликовать комментарий, но он слишком длинный. – none

Смежные вопросы