본문으로 건너뛰기
Previous
Next
C++ std::filesystem::path | Cross-platform paths in C++17

C++ std::filesystem::path | Cross-platform paths in C++17

C++ std::filesystem::path | Cross-platform paths in C++17

이 글의 핵심

Use std::filesystem::path to join, normalize, and inspect paths portably. Covers filename, extension, parent_path, absolute, canonical, weakly_canonical, and practical rename and backup patterns.

Introduction

std::filesystem::path is the C++17 class for portable path handling.

1. What is path?

Basic usage

#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
int main() {
    fs::path p = "/home/user/file.txt";
    fs::path p2 = "C:\\Users\\user\\file.txt";  // Windows
    
    std::cout << p << std::endl;
    std::cout << p2 << std::endl;
    
    return 0;
}

Features:

  • Platform-independent
  • Automatic separator handling (/, \\)
  • Rich API for decomposition and manipulation

2. Path manipulation

Decomposition

#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
int main() {
    fs::path p = "/home/user/documents/report.pdf";
    
    std::cout << "Full: " << p << std::endl;
    std::cout << "Filename: " << p.filename() << std::endl;      // "report.pdf"
    std::cout << "Extension: " << p.extension() << std::endl;     // ".pdf"
    std::cout << "Stem: " << p.stem() << std::endl;             // "report"
    std::cout << "Parent: " << p.parent_path() << std::endl;    // "/home/user/documents"
    std::cout << "Root: " << p.root_path() << std::endl;          // "/"
    
    return 0;
}

Joining paths

fs::path dir = "/home/user";
fs::path file = "file.txt";
// / operator
fs::path full = dir / file;  // "/home/user/file.txt"
// /= operator
fs::path p = "/home/user";
p /= "documents";
p /= "file.txt";
std::cout << p << std::endl;  // "/home/user/documents/file.txt"
// append
fs::path p2 = "/home";
p2.append("user").append("file.txt");

3. Path normalization

Absolute paths

fs::path p = "file.txt";
fs::path abs = fs::absolute(p);
std::cout << abs << std::endl;  // e.g. "/current/directory/file.txt"

Canonical paths

fs::path p = "/home/user/../user/./file.txt";
// Canonical (target must exist)
fs::path canonical = fs::canonical(p);
std::cout << canonical << std::endl;  // "/home/user/file.txt"
// weakly_canonical (need not exist)
fs::path p2 = "/home/user/nonexistent.txt";
fs::path weak = fs::weakly_canonical(p2);
std::cout << weak << std::endl;

Relative paths

fs::path abs = "/home/user/documents/file.txt";
fs::path base = "/home/user";
fs::path rel = fs::relative(abs, base);
std::cout << rel << std::endl;  // "documents/file.txt"

4. Path properties

fs::path p = "/home/user/file.txt";
if (p.is_absolute()) {
    std::cout << "Absolute path" << std::endl;
}
if (p.is_relative()) {
    std::cout << "Relative path" << std::endl;
}
if (p.empty()) {
    std::cout << "Empty path" << std::endl;
}
if (fs::exists(p)) {
    std::cout << "Exists" << std::endl;
}

5. Extensions

Changing extensions

fs::path p = "document.txt";
p.replace_extension(".pdf");
std::cout << p << std::endl;  // "document.pdf"
p.replace_extension();
std::cout << p << std::endl;  // "document"
p.replace_extension(".docx");
std::cout << p << std::endl;  // "document.docx"

Checking extensions

#include <vector>
#include <algorithm>
fs::path p = "image.png";
if (p.extension() == ".png") {
    std::cout << "PNG file" << std::endl;
}
std::vector<std::string> image_exts = {".png", ".jpg", ".jpeg", ".gif"};
if (std::find(image_exts.begin(), image_exts.end(), p.extension()) != image_exts.end()) {
    std::cout << "Image file" << std::endl;
}

6. Comparing paths

fs::path p1 = "/home/user/file.txt";
fs::path p2 = "/home/user/file.txt";
fs::path p3 = "/home/user/other.txt";
if (p1 == p2) {
    std::cout << "Equal" << std::endl;
}
if (p1 != p3) {
    std::cout << "Different" << std::endl;
}
// Case sensitivity is platform-dependent
// Windows: often case-insensitive
// Linux: case-sensitive

7. Practical examples

Example 1: Batch extension rename

#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
void rename_extensions(const fs::path& dir, 
                       const std::string& old_ext, 
                       const std::string& new_ext) {
    for (const auto& entry : fs::directory_iterator(dir)) {
        if (entry.is_regular_file() && entry.path().extension() == old_ext) {
            fs::path new_path = entry.path();
            new_path.replace_extension(new_ext);
            fs::rename(entry.path(), new_path);
            std::cout << "Renamed: " << entry.path().filename() 
                      << " -> " << new_path.filename() << std::endl;
        }
    }
}
int main() {
    rename_extensions("./images", ".jpeg", ".jpg");
    return 0;
}

Example 2: Backup path

fs::path create_backup_path(const fs::path& original) {
    fs::path backup = original;
    backup.replace_extension();
    
    std::string backup_name = backup.filename().string() + "_backup";
    backup = backup.parent_path() / backup_name;
    backup.replace_extension(original.extension());
    
    return backup;
}
int main() {
    fs::path original = "/home/user/document.txt";
    fs::path backup = create_backup_path(original);
    
    std::cout << "Original: " << original << std::endl;
    std::cout << "Backup: " << backup << std::endl;
    
    return 0;
}

Summary

Key points

  1. path: portable path type in C++17
  2. / operator: join segments
  3. filename(), extension(), stem(): decomposition
  4. absolute(): resolve against current directory
  5. canonical(): full normalization (path must exist)

Common methods

MethodRole
filename()File name
extension()Extension including dot
stem()File name without extension
parent_path()Parent directory
root_path()Root component
replace_extension()Change extension

Next steps



자주 묻는 질문 (FAQ)

Q. 이 내용을 실무에서 언제 쓰나요?

A. Use std::filesystem::path to join, normalize, and inspect paths portably. Covers filename, extension, parent_path, absol… 실무에서는 위 본문의 예제와 선택 가이드를 참고해 적용하면 됩니다.

Q. 선행으로 읽으면 좋은 글은?

A. 각 글 하단의 이전 글 또는 관련 글 링크를 따라가면 순서대로 배울 수 있습니다. C++ 시리즈 목차에서 전체 흐름을 확인할 수 있습니다.

Q. 더 깊이 공부하려면?

A. cppreference와 해당 라이브러리 공식 문서를 참고하세요. 글 말미의 참고 자료 링크도 활용하면 좋습니다.


같이 보면 좋은 글 (내부 링크)

이 주제와 연결되는 다른 글입니다.


이 글에서 다루는 키워드 (관련 검색어)

C++, path, filesystem, C++17, cross-platform 등으로 검색하시면 이 글이 도움이 됩니다.