【问题标题】:How to replace the home directory with a tilde? Linux如何用波浪号替换主目录? Linux
【发布时间】:2018-02-13 05:06:19
【问题描述】:

我目前正在用 C++ 制作一个 shell,我已经能够使用 getcwd() 将绝对目录作为提示输出,但是当用户到达主目录时,我想输出一个波浪号而不是主目录目录。

所以例如代替

[bb@bbmachine bb]

我想输出

[bb@bbmachine ~]

我该怎么做?

【问题讨论】:

  • $HOME 环境变量。因此,只需获取该值并用它替换 ~,反之亦然。
  • 没有。不要写已经存在的函数stackoverflow.com/questions/15991241/…
  • 不,OP不想扩展 ~,而是用~替换/home/user/

标签: c++ linux tilde-expansion


【解决方案1】:

首先阅读globbing,尤其是glob(7)。对于以波浪号~ 开头的路径的扩展,请考虑wordexp(3)glob(3)

要显示以主目录开头的路径,您需要获取该主目录。您可以在getuid(2) 的结果上使用getenv(3),如getenv("HOME")(在极少数病理情况下可能会失败)或getpwuid(3)(甚至getpw(3))。主目录(当getpwuid 成功时)由pw_dir 字段给出。另见credentials(7)(和execve(2)...)

getenv("HOME")getpwuid(getuid()) 失败或给出不一致的结果(关于用户的主目录)的情况很少见。我相信你应该发现失败,但你可能不关心不一致。另见environ(7)。您甚至可以考虑 GNU 特定的 secure_getenv(3)

顺便说一句,您可以缓存主目录,即在您的 shell 中计算一次。不太可能经常更改。

您还可以决定使用realpath(3) 规范化路径。

您肯定有极端情况:假设您的进程在@987654347 下运行,您是否要将/home/john/../mary/ 显示为~/../mary/home/mary/~mary,(或者甚至将其保留为/home/john/../mary) @uid? (johnmary 都作为用户名存在于 passwd(5) 中,主目录为 /home/john//home/mary/)。那么/home/john/../../proc/$$/maps(见proc(5))呢?

您需要决定如何处理这些极端情况或病态情况,并记录您的 shell 的行为。

(提到的函数有一个 C API,你可能想在你的 C++ 代码中使用extern "C"

【讨论】:

    【解决方案2】:

    正是@TheDude 所说的。这是一些伪代码。

    #include "pwd.h"
    #include <string>
    string home=getenv("HOME");
    int location=yourPathString.find(home);
    length=home.length();
    originalLength=yourPathString.length();
    string newString=yourPathString.substr(0,location);
    newString+= "~";
    newString+= yourPathString.substr(location+length,originalLength);
    

    这应该会给你正确的想法,但请记住,文档和 Google 是你的朋友。String Reference

    【讨论】:

    • 我刚上网看的,你可以把这几行和STD::string::replace结合起来
    • 您的代码忘记处理(不太可能)失败,可能不需要pwd.h
    • 我忘记了 getenv() 在什么库中。而且我确信会有问题。总是有的。
    • getenv 来自stdlib.hmangetenv(3) 这样的页面很有帮助
    【解决方案3】:

    你可以像这样使用wordexp

    #include <wordexp.h>
    
    // put all the horrible bits into a function
    std::string wordexp(std::string var, int flags = 0)
    {
        wordexp_t p;
        if(!wordexp(var.c_str(), &p, flags))
        {
            if(p.we_wordc && p.we_wordv[0])
                var = p.we_wordv[0];
            wordfree(&p);
        }
        return var;
    }
    
    int main()
    {
        auto const HOME = wordexp("~");
    
        std::string path = "/home/galik/wibble";
    
        if(path.find(HOME) == 0)
            path.replace(0, HOME.size(), "~");
    
        std::cout << path << '\n';
    }
    

    输出:

    ~/wibble
    

    【讨论】:

    • 你不需要wordexp来扩展~,因为你可以使用更短的getenv("HOME")(你需要检查getenv不会返回NULL,这这里是病态的)
    • @BasileStarynkevitch 是的,但如果你正在编写一个 shell(就像 OP 一样),那么 wordexpand 可能是方便使用的东西。此外,我喜欢对 ~ 本身进行测试的对称性,以便检测 ~ 它感觉更健壮。
    猜你喜欢
    • 2010-11-03
    • 2013-07-10
    • 2012-04-19
    • 2012-09-04
    • 1970-01-01
    • 2014-01-19
    • 1970-01-01
    • 2011-08-10
    相关资源
    最近更新 更多