ファイル名を変更したいのtxt
ですが、どうすればいいのかわかりません。
たとえば、C++プログラムで名前をに変更foo.txt
したいとします。boo.txt
ファイル名を変更したいのtxt
ですが、どうすればいいのかわかりません。
たとえば、C++プログラムで名前をに変更foo.txt
したいとします。boo.txt
#include <stdio.h>
(または<cstdio>
)および使用rename
(またはstd::rename
):
rename("oldname.txt", "newname.txt");
一般に信じられていることとは異なり、これは標準ライブラリに含まれており、ある程度まで移植可能です。もちろん、文字列の許容内容はターゲットシステムによって異なります。
ファイルシステムのサポートは特にC++標準ライブラリにはありません。Jerry Coffinの答えが示すように、実際にはstdioに名前変更機能があります(私が共有した一般的な信念とは異なります)。ただし、標準ライブラリでカバーされていないファイルシステム関連のアプライアンスが多数あるため、Boost :: Filesystemが存在します(特に、ディレクトリの操作とファイルに関する情報の取得)。
これは、C ++の制約を緩和するための設計上の決定です(つまり、ファイルの概念が存在しない組み込みシステムを含む幅広いプラットフォームでのコンパイルを可能にします)。
ファイル操作を実行するには、次の2つのオプションがあります。
ターゲットOSのAPIを使用する
プラットフォーム間で統一されたインターフェースを提供するライブラリを使用する
Boost :: Filesystemは、プラットフォームの違いを抽象化するC++ライブラリです。
Boost :: Filesystem::renameを使用してファイルの名前を変更できます。
<filesystem>
アップデート!数年後<filesystem>
、C++標準になりました。したがって、他の投稿で言及されている苦情と「C ++はファイルシステムを直接サポートしていません」というコメントは、もはや有効ではありません。
ISO c ++ 17以降をサポートするコンパイラでstd::filesystem::rename
、次のように使用および実行できます。
#include <filesystem> // std::filesystem::rename
#include <string_view> // std::string_view
using namespace std::literals;
int main()
{
const std::filesystem::path path{ "D:/...complete directory" };
std::filesystem::rename(path / "foo.txt"sv, path / "bar.txt"sv);
}
特定の条件下または特定の拡張子で、ディレクトリ内のファイルのグループの名前を変更する必要がある場合はどうなりますか。それでは、ロジックをクラスにラップしましょう。
#include <filesystem> // std::filesystem::rename
#include <regex> // std::regex_replace
#include <iostream>
#include <string>
using namespace std::string_literals;
namespace fs = std::filesystem;
class FileRenamer /* final */
{
private:
const fs::path mPath;
const fs::path mExtension;
private:
template<typename LogicFunc>
bool renameImpli(const LogicFunc& func, const fs::path& extension = {}) noexcept
{
bool result = true;
const fs::path extToCheck = extension.empty() ? this->mExtension : extension;
// iterate through all the files in the given directory
for (const auto& dirEntry : fs::directory_iterator(mPath))
{
if (fs::is_regular_file(dirEntry) && dirEntry.path().extension() == extToCheck)
{
const std::string currentFileName = dirEntry.path().filename().string();
const std::string newFileName = std::invoke(func, currentFileName);
try
{
fs::rename(mPath / currentFileName, mPath / newFileName);
}
catch (fs::filesystem_error& error) // if the renaming was unsuccessful
{
std::cout << error.code() << "\n" << error.what() << "\n";
result = false; // at least one of the renaming was unsuccessful!
}
}
}
return result;
}
public:
explicit FileRenamer(fs::path path, fs::path extension = { ".txt" }) noexcept
: mPath{ std::move(path) }
, mExtension{ std::move(extension) }
{}
// other constructors as per!
bool findAndReplace(const std::string& findWhat, const std::string& replaceWith, const fs::path& extension = {})
{
const auto logic = [&](const std::string& currentFileName) noexcept {
return std::regex_replace(currentFileName, std::regex{ findWhat }, replaceWith);
};
return renameImpli(logic, extension);
}
bool renameAll(const std::string& fileName, fs::path extension = {})
{
auto index{ 1u };
const auto logic = [&](const std::string&) noexcept {
return std::to_string(index++) + " - "s + fileName + extension.string();
};
return renameImpli(logic, extension);
}
};
int main()
{
FileRenamer fileRenamer{ "D:/"}; // ...complete directory
/*! Rename the files in the given directory with specific extension (.txt by default)
* in such a way that, filename contained the passed string (i.e. here "foo") will be
* replaced to what mentioned (i.e. here "bar").
* Ex: foo.txt --> bar.txt
* pre_foo_post.txt --> File of bar.txt
* File of foo.txt --> pre_bar_post.txt
*/
fileRenamer.findAndReplace("foo"s, "bar"s);
/*! All the files in the given directory with specific extension (.txt by default)
* will be replaced to specific filename provided, additional with an index.
* Ex: foo.txt --> 1 - foo.txt
* pre_foo_post.txt --> 2 - foo.txt
* File of foo.txt --> 3 - foo.txt
*/
fileRenamer.renameAll("foo", ".txt");
}