Как определить, существует ли каталог (а не файл) с использованием С++ в Linux? Я попытался использовать функцию stat(), но он вернулся положительно, когда файл был найден. Я только хочу узнать, является ли введенная строка каталогом, а не чем-то еще.
С++ - определение того, существует ли каталог (а не файл) в Linux
Ответ 1
В соответствии с man (2) stat вы можете использовать макрос S_ISDIR в поле st_mode:
bool isdir = S_ISDIR(st.st_mode);
Заметьте, я бы рекомендовал использовать Boost и/или Qt4, чтобы упростить кросс-платформенную поддержку, если ваше программное обеспечение может быть жизнеспособным на других ОС.
Ответ 2
как насчет того, что я нашел здесь
#include <dirent.h>
bool DirectoryExists( const char* pzPath )
{
if ( pzPath == NULL) return false;
DIR *pDir;
bool bExists = false;
pDir = opendir (pzPath);
if (pDir != NULL)
{
bExists = true;
(void) closedir (pDir);
}
return bExists;
}
Или используя stat
struct stat st;
if(stat("/tmp",&st) == 0)
if(st.st_mode & S_IFDIR != 0)
printf(" /tmp is present\n");
Ответ 3
Если вы можете проверить увеличить библиотеку файловой системы. Это отличный способ справиться с такими проблемами в общем и переносном режиме.
В этом случае было бы достаточно использовать:
#include "boost/filesystem.hpp"
using namespace boost::filesystem;
...
if ( !exists( "test/mydir" ) ) {bla bla}
Ответ 4
То, как я понимаю ваш вопрос, таков: у вас есть путь, скажем, /foo/bar/baz
(baz - файл), и вы хотите знать, существует ли /foo/bar
. Если это так, решение выглядит примерно так (непроверено):
char *myDir = dirname(myPath);
struct stat myStat;
if ((stat(myDir, &myStat) == 0) && (((myStat.st_mode) & S_IFMT) == S_IFDIR)) {
// myDir exists and is a directory.
}
Ответ 5
Если вы хотите узнать, существует ли каталог, потому что вы хотите что-то сделать с ним, если это так (создайте файл/каталог внутри, сканируйте его содержимое и т.д.), вы должны просто пойти и сделать то, что вы хотите сделать, затем проверьте, не сработало ли оно, и если да, сообщите пользователю strerror(errno)
пользователю. Это общий принцип программирования под Unix: не пытайтесь выяснить, будет ли то, что вы хотите сделать, будет работать. Попытайтесь, а затем посмотрите, не сработало ли оно.
Если вы хотите вести себя специально, если что-то не удалось, потому что каталог не существует (например, если вы хотите создать файл и все необходимые каталоги), вы можете проверить errno == ENOENT
после open
выходит из строя.
Я вижу, что один из респондентов рекомендовал использовать boost::filesystem
. Я бы хотел одобрить эту рекомендацию, но, к сожалению, я не могу, потому что boost::filesystem
не только для заголовка, а для всех модулей Boost, отличных от заголовков, есть ужасная запись, вызывающая таинственный поломка, если вы обновляете общую библиотеку без перекомпиляции приложение, или даже если вам просто не удалось скомпилировать приложение с точно такими же флагами, которые использовались для компиляции разделяемой библиотеки. Удержание гонения просто не стоит.
Ответ 6
С С++ 17 вы можете использовать std::filesystem
, в С++ 14 std::experimental::filesystem
уже доступно. Оба позволяют использовать filesystem::is_directory()
.
С++ 17:
#include <filesystem>
std::filesystem::path myDirectory = "my/directory/path";
if (std::filesystem::path::is_directory(myDirectory)) {
if (std::filesystem::path::exists(myDirectory)) {
// Process existing directory.
}
}
С++ 14:
#include <experimental/filesystem>
std::experimental::filesystem::path myDirectory = "my/directory/path";
if (std::experimental::filesystem::path::is_directory(myDirectory)) {
if (std::experimental::filesystem::path::exists(myDirectory)) {
// Process existing directory.
}
}
Примечание:
Обе функции перебрасывают filesystem_error в случае ошибок. Если вы хотите избежать перехвата исключений, используйте перегруженные варианты с std::error_code
в качестве второго параметра. Например.
std::error_code errorCode;
bool error = false;
std::filesystem::path myDirectory = "my/directory/path";
if (std::filesystem::path::is_directory(myDirectory, errorCode)) {
if (std::filesystem::path::exists(myDirectory, errorCode)) {
// Process existing directory.
}
else {
error = true;
}
}
else {
error = true;
}
if (error) {
std::cout << errorCode.message() << std::endl;
}