简体   繁体   English

检查 Unix 中是否存在目录(系统调用)

[英]Checking if a directory exists in Unix (system call)

I am not able to find a solution to my problem online.我无法在网上找到解决我的问题的方法。

I would like to call a function in Unix, pass in the path of a directory, and know if it exists.我想在 Unix 中调用一个函数,传入一个目录的路径,并知道它是否存在。 opendir() returns an error if a directory does not exist, but my goal is not to actually open, check the error, close it if no error, but rather just check if a file is a directory or not.如果目录不存在, opendir()将返回错误,但我的目标不是实际打开,检查错误,如果没有错误则关闭它,而只是检查文件是否为目录。

Is there any convenient way to do that please?请问有什么方便的方法吗?

There are two relevant functions on POSIX systems: stat() and lstat() . POSIX 系统上有两个相关函数: stat() 和 lstat() These are used to find out whether a pathname refers to an actual object that you have permission to access, and if so, the data returned tells you what type of object it is.这些用于查明路径名是否引用了您有权访问的实际对象,如果是,则返回的数据会告诉您它是什么类型的对象。 The difference between stat() and lstat() is that if the name you give is a symbolic link, stat() follows the symbolic link (or links if they are chained together) and reports on the object at the end of the chain of links, whereas lstat() reports on the symbolic link itself. stat()lstat()之间的区别在于,如果您给的名称是符号链接,则stat()会跟随符号链接(或链接,如果它们链接在一起)并报告位于链末尾的对象链接,而lstat()报告符号链接本身。

#include <sys/stat.h>

struct stat sb;

if (stat(pathname, &sb) == 0 && S_ISDIR(sb.st_mode))
{
    ...it is a directory...
}

If the function indicates it was successful, you use the S_ISDIR() macro from <sys/stat.h> to determine whether the file is actually a directory.如果函数指示它成功,则使用<sys/stat.h>中的 S_ISDIR() 宏来确定文件是否实际上是目录。

You can also check for other file types using other S_IS* macros:您还可以使用其他S_IS*宏检查其他文件类型:

  • S_ISDIR — directory S_ISDIR — 目录
  • S_ISREG — regular file S_ISREG — 常规文件
  • S_ISCHR — character device S_ISCHR — 字符设备
  • S_ISBLK — block device S_ISBLK — 块设备
  • S_ISFIFO — FIFO S_ISFIFO — 先进先出
  • S_ISLNK — symbolic link S_ISLNK — 符号链接
  • S_ISSOCK — socket S_ISSOCK — 套接字

(Some systems provide a few other file types too; S_ISDOOR is available on Solaris, for example.) (一些系统还提供了一些其他文件类型;例如, S_ISDOOR在 Solaris 上可用。)

You can make use of the stat system call by passing it the name of the directory as the first argument.您可以通过将目录名称作为第一个参数传递给stat系统调用来使用它。 If the directory exists a 0 is returned else -1 is returned and errno will be set to ENOENT如果目录存在则返回0否则返回-1并且 errno 将被设置为ENOENT

EDIT:编辑:

If the return value is 0 you would need an additional check to ensure that the argument is actually a directory and not a file/symlink/char special file/blk special file/FIFO file.如果返回值为0 ,则需要额外检查以确保参数实际上是一个目录,而不是 file/symlink/char 特殊文件/blk 特殊文件/FIFO 文件。 You can make use of the st_mode field of the stat structure for this.为此,您可以使用stat structurest_mode字段。

If you're talking about from a shell, there's a good SO answer here. 如果你是在谈论shell,那么这里有一个很好的答案 To summarize that answer: 总结一下答案:

if [ -d "$DIRECTORY" ]; then
    # Control will enter here if $DIRECTORY exists
fi

If you're talking from inside a C program, you can use stat() : 如果你在C程序内部进行交谈,可以使用stat()

{
    struct stat st;
    if(stat("/tmp",&st) == 0)
        printf(" /tmp is present\n");
}

你可以使用test -d

Tested and working fine: 经过测试和正常工作:

int file_exist (char *filename)
{
    char s[200];
    sprintf(s, "test -e %s", filename);
    if (system(s) == 0){
        return 1;
    }else{
        return 0;
    }
}

If you don't really care about type of this filesystem object, access(name, F_OK) checks for exsistence of something with this name.如果您并不真正关心此文件系统对象的类型,那么 access(name, F_OK) 会检查是否存在具有此名称的内容。 If you need to be sure this is directory, use stat() and check type with S_ISDIR() macro.如果您需要确定这是目录,请使用 stat() 并使用 S_ISDIR() 宏检查类型。

Another simple way would be:另一种简单的方法是:

int check(unsigned const char type) {
    if(type == DT_REG)
        return 1;
    if(type == DT_DIR)
        return 0;
    return -1;
}

You can then pass struct dirent* object's d_type to check function.然后,您可以将struct dirent*对象的 d_type 传递给检查函数。

If check returns 1, then that path points to regular file.如果检查返回 1,则该路径指向常规文件。

If check returns 0, then that path points to a directory.如果检查返回 0,则该路径指向一个目录。

Otherwise, it is neither a file or a directory (it can be a Block Device/Symbolic Link, etc..)否则,它既不是文件也不是目录(可以是块设备/符号链接等)

I think the function stat may do what you want (I havent test it for directories). 我认为函数stat可以做你想要的(我没有测试它的目录)。 In C++, you can also use the boost::filesystem library. 在C ++中,您还可以使用boost :: filesystem库。

C++17 C++17

Use std::filesystem::is_directory :使用std::filesystem::is_directory

#include <filesystem>

void myFunc(const std::filesystem::path& directoryPath_c)
{
    if (std::filesystem::is_directory(directoryPath_c)) {
    //if (std::filesystem::exists(directoryPath_c)) { // Alternative*
        // do something.
    }
}

Or in its noexept version:或者在它的noexept版本中:

#include <filesystem>

void myFunc(const std::filesystem::path& directoryPath_c)
{
    std::error_code ec{};
    if (std::filesystem::is_directory(directoryPath_c, ec)) {
    //if (std::filesystem::exists(directoryPath_c, ec)) { // An alternative*
        // do something.
    }
}
  • The disadvantage of the alternative is, that if directoryPath_c exists as a regular-file, std::filesystem::exists(directoryPath_c) returns true despite the folder does not exists.替代方法的缺点是,如果directoryPath_c作为常规文件存在,则std::filesystem::exists(directoryPath_c)将返回true ,尽管该文件夹不存在。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM