Как определить, существует ли каталог (не файл) с использованием С++ в Linux? Я попытался использовать функцию stat(), но она вернула положительный результат, когда файл был найден. Я только хочу узнать, является ли введенная строка каталогом, а не чем-то еще.
C++ - определение, существует ли каталог (не файл) в Linux
Ответы (6)
Согласно man(2) stat, вы можете использовать макрос S_ISDIR в поле st_mode:
bool isdir = S_ISDIR(st.st_mode);
Примечание: я бы рекомендовал использовать Boost и/или Qt4, чтобы упростить кросс-платформенную поддержку, если ваше программное обеспечение может работать на других ОС.
как насчет того, что я нашел здесь
#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;
}
Или используя стат.
struct stat st;
if(stat("/tmp",&st) == 0)
if(st.st_mode & S_IFDIR != 0)
printf(" /tmp is present\n");
and
. (myStat.st_mode) & S_IFMT) == S_IFDIR)
. спасибо ДаркДаст.
- person ayush; 13.02.2011
Если вы можете проверить библиотеку файловой системы Boost а>. Это отличный способ справиться с такого рода проблемами универсальным и переносимым способом.
В этом случае достаточно будет использовать:
#include "boost/filesystem.hpp"
using namespace boost::filesystem;
...
if ( !exists( "test/mydir" ) ) {bla bla}
Я так понимаю ваш вопрос: у вас есть путь, скажем, /foo/bar/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.
}
/foo/bar/baz
не существует, либо он существует и является каталогом, либо существует и не является каталогом; он не может существовать как одновременно как каталог и не как каталог.
- person John Bartholomew; 13.02.2011
st_mode & S_IFMT
вместо S_ISDIR
является плохим стилем.
- person zwol; 13.02.2011
st_mode
. Либо используйте мой код для проверки флага каталога, либо макроса S_ISDIR
, как показано в ответе OneOfOne.
- person DarkDust; 13.02.2011
В C++17** std::filesystem
предоставляет два варианта определения существования дорожка:
is_directory()
определяет, является ли путь каталогом и существует ли он в реальной файловой системе.exists()
просто определяет, существует ли путь в реальной файловой системе (не проверяя, если это каталог)
Пример (без обработки ошибок):
#include <iostream>
#include <filesystem> // C++17
//#include <experimental/filesystem> // C++14
namespace fs = std::filesystem;
//namespace fs = std::experimental::filesystem; // C++14
int main()
{
// Prepare.
const auto processWorkingDir = fs::current_path();
const auto existingDir = processWorkingDir / "existing/directory"; // Should exist in file system.
const auto notExistingDir = processWorkingDir / "fake/path";
const auto file = processWorkingDir / "file.ext"; // Should exist in file system.
// Test.
std::cout
<< "existing dir:\t" << fs::is_directory(existingDir) << "\n"
<< "fake dir:\t" << fs::is_directory(notExistingDir) << "\n"
<< "existing file:\t" << fs::is_directory(file) << "\n\n";
std::cout
<< "existing dir:\t" << fs::exists(existingDir) << "\n"
<< "fake dir:\t" << fs::exists(notExistingDir) << "\n"
<< "existing file:\t" << fs::exists(file);
}
Возможный вывод:
existing dir: 1
fake dir: 0
existing file: 0
existing dir: 1
fake dir: 0
existing file: 1
**в C++14 доступен std::experimental::filesystem
Обе функции выдают filesystem_error
в случае ошибок. Если вы хотите избежать перехвата исключений, используйте перегруженные варианты с std::error_code
в качестве второго. параметр.
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
bool isExistingDir(const fs::path& p) noexcept
{
try
{
return fs::is_directory(p);
}
catch (std::exception& e)
{
// Output the error message.
const auto theError = std::string{ e.what() };
std::cerr << theError;
return false;
}
}
bool isExistingDirEC(const fs::path& p) noexcept
{
std::error_code ec;
const auto isDir = fs::is_directory(p, ec);
if (ec)
{
// Output the error message.
const auto theError = ec.message();
std::cerr << theError;
return false;
}
else
{
return isDir;
}
}
int main()
{
const auto notExistingPath = fs::path{ "\xa0\xa1" };
isExistingDir(notExistingPath);
isExistingDirEC(notExistingPath);
}
is_directory()
, а потом exists()
? Кроме того, действительно ли нужен exists()
?
- person Andrew; 26.08.2018
if (!is_directory("myDir")) { create_directory("myDir"); if (!is_directory("myDir")) { return false; } }
и все работало нормально (создавал папку, если она не существовала, не создавал ее, если она существовала в виде папки, возвращал false, если она существовала в виде файла).
- person Andrew; 26.08.2018
exists()
действительно было лишним! Я обновил пример. Поскольку вопрос не включает создание каталога, я опускаю это в ответе.
- person Roi Danton; 26.08.2018
Если вы хотите узнать, существует ли каталог, потому что вы хотите что-то сделать с ним, если он существует (создать файл/каталог внутри, отсканировать его содержимое и т. д.), вы должны просто пойти дальше и сделать все, что хотите, затем проверьте если это не удалось, и если да, сообщите strerror(errno)
пользователю. Это общий принцип программирования под Unix: не пытайтесь выяснить, будет ли работать то, что вы хотите сделать. Попробуйте, а потом посмотрите, не получилось ли.
Если вы хотите вести себя особым образом, если что-то не удалось, потому что каталог не существует (например, если вы хотите создать файл и все необходимые содержащие каталоги), вы проверяете errno == ENOENT
после сбоя open
.
Я вижу, что один респондент рекомендовал использовать boost::filesystem
. Я хотел бы поддержать эту рекомендацию, но, к сожалению, не могу, потому что boost::filesystem
предназначен не только для заголовков, а все модули Boost, не предназначенные только для заголовков, имеют ужасный послужной список вызывающих загадочные поломки при обновлении. общую библиотеку без перекомпиляции приложения или даже если вам просто не удалось скомпилировать приложение с точно теми же флагами, которые использовались для компиляции общей библиотеки. Горе обслуживания просто не стоит.
opendir
и посмотреть, не сработает ли он (что должно произойти при применении к обычному файлу)?
- person zwol; 13.02.2011
stat()
должно работать. Как вы его использовали? - person John Bartholomew   schedule 13.02.2011