c++ - 如何使用 boost::filesystem "normalize"路径名?

标签 c++ boost filesystems

我们在我们的应用程序中使用了 boost::filesystem。我有一个“完整”路径,它是通过将多个路径连接在一起构建的:

#include <boost/filesystem/operations.hpp>
#include <iostream>
     
namespace bf = boost::filesystem;

int main()
{
    bf::path root("c:\\some\\deep\\application\\folder");
    bf::path subdir("..\\configuration\\instance");
    bf::path cfgfile("..\\instance\\myfile.cfg");

    bf::path final ( root / subdir / cfgfile);

    cout << final.file_string();
}

最终路径打印为:

c:\some\deep\application\folder\..\configuration\instance\..\instance\myfile.cfg

这是一个有效的路径,但是当我将它显示给用户时,我希望它被规范化。(注意:我什至不确定“规范化”是否是正确的词为了这)。像这样:

c:\some\deep\application\configuration\instance\myfile.cfg

早期版本的 Boost 有一个 normalize() 函数 - 但它似乎已被弃用和删除(没有任何解释)。

我不应该使用 BOOST_FILESYSTEM_NO_DEPRECATED 宏有什么理由吗?是否有其他方法可以使用 Boost Filesystem 库执行此操作?还是应该编写代码直接将路径作为字符串进行操作?

最佳答案

Boost v1.48及以上

您可以使用boost::filesystem::canonical:

path canonical(const path& p, const path& base = current_path());
path canonical(const path& p, system::error_code& ec);
path canonical(const path& p, const path& base, system::error_code& ec);

http://www.boost.org/doc/libs/1_48_0/libs/filesystem/v3/doc/reference.html#canonical

v1.48及以上版本还提供了解析符号链接(symbolic link)的boost::filesystem::read_symlink函数。

Boost v1.48 之前的版本

如其他答案中所述,您无法规范化,因为 boost::filesystem 无法跟随符号链接(symbolic link)。但是,您可以编写一个“尽可能”规范化的函数(假设“.”和“..”被正常处理),因为 boost 提供了确定文件是否为符号链接(symbolic link)的能力。

也就是说,如果“..”的父级是符号链接(symbolic link),那么您必须保留它,否则删除它可能是安全的,删除“.”可能总是安全的。

它类似于操作实际的字符串,但稍微更优雅。

boost::filesystem::path resolve(
    const boost::filesystem::path& p,
    const boost::filesystem::path& base = boost::filesystem::current_path())
{
    boost::filesystem::path abs_p = boost::filesystem::absolute(p,base);
    boost::filesystem::path result;
    for(boost::filesystem::path::iterator it=abs_p.begin();
        it!=abs_p.end();
        ++it)
    {
        if(*it == "..")
        {
            // /a/b/.. is not necessarily /a if b is a symbolic link
            if(boost::filesystem::is_symlink(result) )
                result /= *it;
            // /a/b/../.. is not /a/b/.. under most circumstances
            // We can end up with ..s in our result because of symbolic links
            else if(result.filename() == "..")
                result /= *it;
            // Otherwise it should be safe to resolve the parent
            else
                result = result.parent_path();
        }
        else if(*it == ".")
        {
            // Ignore
        }
        else
        {
            // Just cat other path entries
            result /= *it;
        }
    }
    return result;
}

关于c++ - 如何使用 boost::filesystem "normalize"路径名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21267735/

相关文章:

c++ - 使用自定义着色器的 OpenGL/ES 渲染 = 网格上的伪影

c++ - 二进制表达式 Person 和 Person 的无效操作数

c - 给定目录名,如何在 C 中找到它所在的文件系统?

c++ - 行尾的双反斜杠有什么作用?

C++ 套接字只接收先发送?

c++ - 多平台原子增量

c++ - 如何从 2d Boost.MultiArray 中获取子数组?

c++ - Boost MPL - 为序列中的每种类型声明一个类

go - 并发文件系统扫描

c++ - 如何使用 SHFILEOPSTRUCT 移动多个文件?