2010-12-29 44 views
18

Tôi đang viết chương trình để kiểm tra xem tệp nào đó là tệp hay là thư mục. Có cách nào tốt hơn để làm điều đó hơn điều này?Kiểm tra xem tệp có phải là thư mục hay chỉ là một tệp

#include <stdio.h> 

#include <sys/types.h> 
#include <dirent.h> 
#include <errno.h> 

int isFile(const char* name) 
{ 
    DIR* directory = opendir(name); 

    if(directory != NULL) 
    { 
    closedir(directory); 
    return 0; 
    } 

    if(errno == ENOTDIR) 
    { 
    return 1; 
    } 

    return -1; 
} 

int main(void) 
{ 
    const char* file = "./testFile"; 
    const char* directory = "./"; 

    printf("Is %s a file? %s.\n", file, 
    ((isFile(file) == 1) ? "Yes" : "No")); 

    printf("Is %s a directory? %s.\n", directory, 
    ((isFile(directory) == 0) ? "Yes" : "No")); 

    return 0; 
} 

Trả lời

36

Bạn có thể gọi stat() chức năng và sử dụng S_ISREG() vĩ mô trên st_mode lĩnh vực cấu trúc stat để xác định xem đường dẫn trỏ của bạn vào một tệp thông thường:

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

int is_regular_file(const char *path) 
{ 
    struct stat path_stat; 
    stat(path, &path_stat); 
    return S_ISREG(path_stat.st_mode); 
} 

Lưu ý rằng có các loại tệp khác ngoài regula rthư mục, như thiết bị, đường ống, liên kết tượng trưng, ​​ổ cắm, v.v. Bạn có thể muốn tính đến các tài khoản đó.

+4

Khi xem xét các trường hợp liên kết tượng trưng, ​​hãy sử dụng lstat() thay vì stat() vì nó không theo liên kết tượng trưng. – Sparky

+3

Có ít nhất một cuộc thảo luận tốt tại [Kiểm tra xem một thư mục có tồn tại không] (http://stackoverflow.com/questions/3828192/checking-if-a-directory-exists-in-unix-system-call/), nơi ' stat() 'và' lstat() 'được thảo luận và tập hợp đầy đủ các loại tệp POSIX được phác thảo. Tôi bị cám dỗ lặp lại câu hỏi này cho câu hỏi đó. Mã nên kiểm tra kết quả của 'stat()', và xử lý các lỗi một cách thích hợp. –

+0

@ Jonathan, câu trả lời đó thực sự hoàn chỉnh hơn tôi, và được đăng ba tháng trước tôi, năm năm trước. Và nó không giống như câu trả lời của riêng tôi sẽ biến mất anyway. Tôi thấy bạn sử dụng Mjölnir trong thẻ '[c]', vì vậy cảm ơn bạn đã bình luận trước khi hành động đơn phương. Tuy nhiên, cuối cùng bạn cũng đúng. Đừng lo, hãy làm những gì bạn phải làm :) –

4

Có, tốt hơn. Kiểm tra stat hoặc fstat chức năng

14

Sử dụng S_ISDIR vĩ mô:

int isDirectory(const char *path) { 
    struct stat statbuf; 
    if (stat(path, &statbuf) != 0) 
     return 0; 
    return S_ISDIR(statbuf.st_mode); 
} 
+0

Bạn quên điền vào cấu trúc 'statbuf' với thông tin. – RedX

+1

Tính năng này hoạt động tốt, chức năng stat sẽ tự điền đầy đủ thông tin. – ismail

+2

Lý tưởng nhất, mã sẽ kiểm tra rằng 'stat' đã làm việc:' if (stat (path, & statbuf)! = 0) trả về 0; '- bởi vì một đối tượng không tồn tại không phải là một thư mục, và nếu bạn không có cho phép 'stat()' nó, nó cũng có thể không tồn tại (ngay cả khi lỗi được báo cáo có liên quan đến quyền). –

1

Thông thường bạn muốn thực hiện kiểm tra này một cách nguyên tắc với kết quả, vì vậy stat() là vô dụng. Thay vào đó, trước tiên, open() chỉ đọc tệp và sử dụng fstat(). Nếu đó là một thư mục, bạn có thể sử dụng fdopendir() để đọc. Hoặc bạn có thể thử mở nó để viết để bắt đầu, và mở sẽ thất bại nếu đó là một thư mục. Một số hệ thống (POSIX 2008, Linux) cũng có một phần mở rộng O_DIRECTORY đến open làm cho cuộc gọi thất bại nếu tên không phải là một thư mục.

Phương pháp của bạn với opendir() cũng tốt nếu bạn muốn có một thư mục, nhưng bạn không nên đóng nó sau đó; bạn nên tiếp tục và sử dụng nó.

Các vấn đề liên quan