使用stat来检测文件是否存在(慢?)

时间:2022-11-23 09:22:02

I'm using code like the following to check whether a file has been created before continuing, thing is the file is showing up in the file browser much before it is being detected by stat... is there a problem with doing this?

我正在使用类似下面的代码来检查文件是否在继续之前已经创建了,事情是文件在文件浏览器中出现之前很久才被stat检测到...这样做有问题吗?

//... do something

struct stat buf;

while(stat("myfile.txt", &buf))
  sleep(1);

//... do something else

alternatively is there a better way to check whether a file exists?

或者有更好的方法来检查文件是否存在?

3 个解决方案

#1


3  

The "stat" system call is collecting different information about the file, such as, for example, a number of hard links pointing to it or its "inode" number. You might want to look at the "access" system call which you can use to perform existence check only by specifying "F_OK" flag in "mode".

“stat”系统调用正在收集关于文件的不同信息,例如指向它的许多硬链接或其“inode”号。您可能希望查看“访问”系统调用,您可以使用该调用仅通过在“模式”中指定“F_OK”标志来执行存在检查。

There is, however, a little problem with your code. It puts the process to sleep for a second every time it checks for file which doesn't exist yet. To avoid that, you have to use inotify API, as suggested by Jerry Coffin, in order to get notified by kernel when file you are waiting for is there. Keep in mind that inotify does not notify you if file is already there, so in fact you need to use both "access" and "inotify" to avoid a race condition when you started watching for a file just after it was created.

但是,您的代码有一点问题。每次检查尚不存在的文件时,它会使进程休眠一秒钟。为避免这种情况,您必须使用initify API,如Jerry Coffin所建议的那样,以便在您等待的文件存在时通知内核。请记住,如果文件已存在,inotify不会通知您,因此实际上您需要同时使用“access”和“inotify”来避免在创建文件后立即开始查看文件时的竞争条件。

There is no better or faster way to check if file exists. If your file browser still shows the file slightly faster than this program detects it, then Greg Hewgill's idea about renaming is probably taking place.

没有更好或更快的方法来检查文件是否存在。如果您的文件浏览器仍然显示该文件比该程序检测到的文件稍快,那么Greg Hewgill关于重命名的想法可能正在发生。

Here is a C++ code example that sets up an inotify watch, checks if file already exists and waits for it otherwise:

这是一个C ++代码示例,用于设置inotify监视,检查文件是否已存在并等待它:

#include <cstdio>
#include <cstring>
#include <string>

#include <unistd.h>
#include <sys/inotify.h>

int
main ()
{
    const std::string directory = "/tmp";
    const std::string filename = "test.txt";
    const std::string fullpath = directory + "/" + filename;

    int fd = inotify_init ();
    int watch = inotify_add_watch (fd, directory.c_str (),
                                   IN_MODIFY | IN_CREATE | IN_MOVED_TO);

    if (access (fullpath.c_str (), F_OK) == 0)
    {
        printf ("File %s exists.\n", fullpath.c_str ());
        return 0;
    }

    char buf [1024 * (sizeof (inotify_event) + 16)];
    ssize_t length;

    bool isCreated = false;

    while (!isCreated)
    {
        length = read (fd, buf, sizeof (buf));
        if (length < 0)
            break;
        inotify_event *event;
        for (size_t i = 0; i < static_cast<size_t> (length);
             i += sizeof (inotify_event) + event->len)
        {
            event = reinterpret_cast<inotify_event *> (&buf[i]);
            if (event->len > 0 && filename == event->name)
            {
                printf ("The file %s was created.\n", event->name);
                isCreated = true;
                break;
            }
        }
    }

    inotify_rm_watch (fd, watch);
    close (fd);
}

#2


4  

Using inotify, you can arrange for the kernel to notify you when a change to the file system (such as a file creation) takes place. This may well be what your file browser is using to know about the file so quickly.

使用inotify,您可以安排内核在发生文件系统更改(例如文件创建)时通知您。这可能是您的文件浏览器用于快速了解文件的内容。

#3


1  

your code will check if the file is there every second. you can use inotify to get an event instead.

您的代码将检查文件是否每秒都在那里。您可以使用inotify来获取活动。

#1


3  

The "stat" system call is collecting different information about the file, such as, for example, a number of hard links pointing to it or its "inode" number. You might want to look at the "access" system call which you can use to perform existence check only by specifying "F_OK" flag in "mode".

“stat”系统调用正在收集关于文件的不同信息,例如指向它的许多硬链接或其“inode”号。您可能希望查看“访问”系统调用,您可以使用该调用仅通过在“模式”中指定“F_OK”标志来执行存在检查。

There is, however, a little problem with your code. It puts the process to sleep for a second every time it checks for file which doesn't exist yet. To avoid that, you have to use inotify API, as suggested by Jerry Coffin, in order to get notified by kernel when file you are waiting for is there. Keep in mind that inotify does not notify you if file is already there, so in fact you need to use both "access" and "inotify" to avoid a race condition when you started watching for a file just after it was created.

但是,您的代码有一点问题。每次检查尚不存在的文件时,它会使进程休眠一秒钟。为避免这种情况,您必须使用initify API,如Jerry Coffin所建议的那样,以便在您等待的文件存在时通知内核。请记住,如果文件已存在,inotify不会通知您,因此实际上您需要同时使用“access”和“inotify”来避免在创建文件后立即开始查看文件时的竞争条件。

There is no better or faster way to check if file exists. If your file browser still shows the file slightly faster than this program detects it, then Greg Hewgill's idea about renaming is probably taking place.

没有更好或更快的方法来检查文件是否存在。如果您的文件浏览器仍然显示该文件比该程序检测到的文件稍快,那么Greg Hewgill关于重命名的想法可能正在发生。

Here is a C++ code example that sets up an inotify watch, checks if file already exists and waits for it otherwise:

这是一个C ++代码示例,用于设置inotify监视,检查文件是否已存在并等待它:

#include <cstdio>
#include <cstring>
#include <string>

#include <unistd.h>
#include <sys/inotify.h>

int
main ()
{
    const std::string directory = "/tmp";
    const std::string filename = "test.txt";
    const std::string fullpath = directory + "/" + filename;

    int fd = inotify_init ();
    int watch = inotify_add_watch (fd, directory.c_str (),
                                   IN_MODIFY | IN_CREATE | IN_MOVED_TO);

    if (access (fullpath.c_str (), F_OK) == 0)
    {
        printf ("File %s exists.\n", fullpath.c_str ());
        return 0;
    }

    char buf [1024 * (sizeof (inotify_event) + 16)];
    ssize_t length;

    bool isCreated = false;

    while (!isCreated)
    {
        length = read (fd, buf, sizeof (buf));
        if (length < 0)
            break;
        inotify_event *event;
        for (size_t i = 0; i < static_cast<size_t> (length);
             i += sizeof (inotify_event) + event->len)
        {
            event = reinterpret_cast<inotify_event *> (&buf[i]);
            if (event->len > 0 && filename == event->name)
            {
                printf ("The file %s was created.\n", event->name);
                isCreated = true;
                break;
            }
        }
    }

    inotify_rm_watch (fd, watch);
    close (fd);
}

#2


4  

Using inotify, you can arrange for the kernel to notify you when a change to the file system (such as a file creation) takes place. This may well be what your file browser is using to know about the file so quickly.

使用inotify,您可以安排内核在发生文件系统更改(例如文件创建)时通知您。这可能是您的文件浏览器用于快速了解文件的内容。

#3


1  

your code will check if the file is there every second. you can use inotify to get an event instead.

您的代码将检查文件是否每秒都在那里。您可以使用inotify来获取活动。