如何在 c++ 中比较(目录)路径

How to compare (directory) paths in c++?

本文关键字:目录 路径 比较 c++      更新时间:2023-10-16

我正在寻找一种方法来检查 2 个字符串在文件系统路径(目录(方面是否相同。例如,此集合中的所有字符串在文件系统路径方面都是相同的:{ /xx//x/x/ },但这两个 - /x/y 不是,即使/y是指向/x的符号链接。我将要编写的程序应该适用于Linux和Windows,所以我正在寻找便携式解决方案。

编辑:

我只使用仅标题的 boost 库,所以boost::filesystem的解决方案对我来说是不行的。我知道Windows API中有UrlCompare,有没有类似linux的东西?

任何非 Boost 解决方案都将涉及系统相关代码(即隐藏在增强中,如果您使用增强(。 而且您必须准确定义你所说的"匹配"是什么意思:应该"./MyFile.xxx""MyFile.xxx"比较平等? "aaa/.../MyFile.xxx""MyFile.xxx"呢?

我处理这个问题的方法是定义一个具有两个数据成员的类,带有"前缀"的std::string(前缀始终为在 Unix 中为空(,以及包含所有路径的std::vector<std::string>元素。 这个类会点有必要的比较函数,并将使用依赖于系统的代码来实现构造 函数;构造函数本身将位于源文件中,并且源文件将包含依赖于计算机的标头(通常通过使用每个变体的单独目录,并通过以下方式选择标头-I/I指定要使用的目录(。 这类事情这可能会进入标题:

inline bool
isPathSeparator( char ch )
{
    return ch == '/';
}
std::string
getHeader( std::string const& fullPathName )
{
    return "";
}
bool
charCompare( char lhs, char rhs )
{
    return lhs < rhs;
}
bool
charMatch( char lhs, char rhs )
{
    return lhs == rhs;
}

对于 Unix,具有:

inline bool
isPathSeparator( char ch )
{
    return ch == '/' || ch == '';
}
std::string
getHeader( std::string const& fullPathName )
{
    return fullPathName.size() > 2 && fullPathName[1] == ':'
        ? fullPathName.substr( 0, 2 )
        : std::string();
}
bool
charCompare( char lhs, char rhs )
{
    return tolower( (unsigned char)lhs) < tolower( (unsigned char)rhs );
}
bool
charMatch( char lhs, char rhs )
{
    return tolower( (unsigned char)lhs ) == tolower( (unsigned char)rhs );
}

对于视窗。

然后,构造函数将使用 getHeader 来初始化标头,并且遍历input.begin() + header.size()input.end(),打破字符串到元素中。 如果遇到"."元素,忽略它,对于".."之一,使用pop_back()取下顶部元素,前提是路径不为空。 之后,它是只是定义要使用的比较器的问题 charComparecharMatch用于charstd::lexicographical_comparestd::equal(在验证大小相等后(与std::string的比较器(可能还有新的类(。 像这样:

struct FileNameCompare
{
    bool operator()( char lhs, char rhs ) const
    {
        return charCompare( lhs, rhs );
    }
    bool operator()( std::string const& lhs, std::string const& rhs ) const
    {
        return std::lexicographical_compare(
            lhs.begin(), lhs.end(),
            rhs.begin(), rhs.end(),
            *this );
    }
    bool operator()( FileName const& lhs, FileName const& rhs ) const
    {
        return (*this)( lhs.prefix, rhs.prefix )
            || ( !(*this)( rhs.prefix, lhs.prefix )
                && std::lexicographical_compare(
                    lhs.elements.begin(), lhs.elements.end(),
                    rhs.elements.begin(), rhs.elements.end(),
                    *this ) );
    }
};
struct FileNameMatch
{
    bool operator()( char lhs, char rhs ) const
    {
        return charMatch( lhs, rhs );
    }
    bool operator()( std::string const& lhs, std::string const& rhs ) const
    {
        return lhs.size() == rhs.size()
            && std::equal( lhs.begin(), lhs.end(), rhs.begin(), *this );
    }
    bool operator()( FileName const& lhs, FileName const& rhs ) const
    {
        return (*this)( lhs.prefix, rhs.prefix )
            && lhs.elements.size() == rhs.elements.size()
            && std::equal( lhs.elements.begin(), lhs.elements.end(),
                           rhs.elements.begin(),
                           *this );
    }
};

应该做这个伎俩。 (请记住,operator()( char, char ) const必须在源文件中;您不能将它们内联在标头中,它不包括定义 charComparecharMatch

std::string path1 = "c:\folder\";
std::string path2 = "c:\folder\folder\..\";
boost::filesystem::equivalent(boost::filesystem::path(path1), boost::filesystem::path(path2)

代码返回 true ,因为文件夹实际上是相同的。

使用 boost::filesystem 库 - 它具有路径比较功能。

编辑:您可以尝试apr - 是的,它不C++,但它是便携式的。

在可移植性方面,Boost文件系统库可能很有用(文档链接(。更具体地说:path.hpp最有用,您可以使用路径比较。

编辑

这个关于 gmane.org 的讨论涉及boost::filesystem的最小仅标头版本。总结:这不存在。因此,您最终将构建自己的抽象库并为其提供跨平台功能。

在Linux下有dirent.h,它是一个POSIX C库。对于Windows,您必须使用Win32 API。但是,还有一个所谓的"目录流库",似乎是跨平台的,可在此处获得(网站是德语(。