C++ でファイルが存在するかどうかを確認する方法
この記事では、ディレクトリ内に特定のファイルが存在するかどうかを確認するための C++ メソッドを紹介します。ただし、以下のチュートリアルは C++ 17 の filesystem
ライブラリをベースにしているので、新しいコンパイラでのみサポートされています。
ディレクトリにファイルが存在するかどうかを調べるには std::filesystem::exists
を使用する
exists
メソッドはパスを引数に取り、既存のファイルやディレクトリに対応する場合は真偽値 true
を返します。以下の例では、任意のファイル名を含むベクトルを初期化して exists
関数でファイルシステム内のファイル名を調べる。なお、exists
メソッドは実行ファイルのあるカレントディレクトリのみをチェックすることに注意してください。
#include <filesystem>
#include <iostream>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::filesystem::exists;
int main() {
vector<string> files_to_check = {"main.cpp", "Makefile", "hello-world"};
for (const auto &file : files_to_check) {
exists(file) ? cout << "Exists\n" : cout << "Doesn't exist\n";
}
return EXIT_SUCCESS;
}
上記のコードは、for_Each
STL アルゴリズムを用いて再実装することができ、コードの再利用性が向上します。
#include <filesystem>
#include <iostream>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::filesystem::exists;
int main() {
vector<string> files_to_check = {"main.cpp", "Makefile", "hello-world"};
auto check = [](const auto &file) {
exists(file) ? cout << "Exists\n" : cout << "Doesn't exist\n";
};
for_each(files_to_check.begin(), files_to_check.end(), check);
return EXIT_SUCCESS;
}
この exists
メソッドは、他の <filesystem>
ライブラリルーチンと組み合わせることで、より有益な情報を得ることができます。is_directory
や is_regular_file
のような <filesystem>
ライブラリルーチンと組み合わせれば、より有益な情報を得ることができます。一般的に、ファイルシステムのメソッドの中にはファイルとディレクトリを区別しないものもありますが、以下のサンプルコードに示すように、特定のファイル型チェック関数を使ってパス名を確認することができます。
#include <filesystem>
#include <iostream>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::filesystem::exists;
using std::filesystem::is_directory;
using std::filesystem::is_regular_file;
int main() {
vector<string> files_to_check = {"main.cpp", "Makefile", "hello-world"};
for (const auto &file : files_to_check) {
if (exists(file)) {
if (is_directory(file)) cout << "Directory exists\n";
if (is_regular_file(file))
cout << "File exists\n";
else
cout << "Exists\n";
} else {
cout << "Doesn't exist\n";
};
};
return EXIT_SUCCESS;
}
ここで、特定のディレクトリに移動して、特定のファイル名が存在するかどうかをチェックしたい場合を考えてみましょう。このためには、current_path
メソッドを利用する必要があります。これは引数を渡さなければカレントディレクトリを返し、引数を与えればカレントディレクトリを指定したパスに変更することができます。プログラムの出力をよりよく確認するために、システムに応じてディレクトリのパスやファイル名を変更することを忘れないようにしてください。
#include <filesystem>
#include <iostream>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::filesystem::current_path;
using std::filesystem::exists;
using std::filesystem::is_directory;
using std::filesystem::is_regular_file;
int main() {
vector<string> files_to_check = {"main.cpp", "Makefile", "hello-world"};
current_path("../");
for (const auto &file : files_to_check) {
exists(file) ? cout << "Exists\n" : cout << "Doesn't exist\n";
}
return EXIT_SUCCESS;
}
また、directory_iterator
を繰り返し実行している間に、現在のユーザがディレクトリ内のファイルに対してどのようなパーミッションを持っているかを確認することもできます。status
メソッドはパーミッションを取得し、perms
という特別なクラスに格納するために使われます。取得したパーミッションは perms
構造体に対してビット単位の操作で表示します。ことができます。以下の例では、所有者のパーミッションのみを抽出しています(一覧はこちら)。
#include <filesystem>
#include <iostream>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::vector;
using std::filesystem::directory_iterator;
using std::filesystem::exists;
using std::filesystem::perms;
using std::string;
int main() {
vector<std::filesystem::perms> f_perm;
string path = "../";
for (const auto& file : directory_iterator(path)) {
cout << file << " - ";
cout << ((file.status().permissions() & perms::owner_read) != perms::none
? "r"
: "-")
<< ((file.status().permissions() & perms::owner_write) != perms::none
? "w"
: "-")
<< ((file.status().permissions() & perms::owner_exec) != perms::none
? "x"
: "-")
<< endl;
}
cout << endl;
return EXIT_SUCCESS;
}