2.9. 我如何像shell里一样扩展在文件名里的'~'?

'~'的标准用法如下:如果单独使用或者后面跟一个'/',那么'~'就被当作当前 用户的home目录,[译者注:事实上'~'就被替换为$HOME环境变量],如果'~'后 直接跟一个用户名,则被替换的就是那个用户的home目录。如果没有合适的匹 配,则shell不会做任何改动。

请注意,有可能一些文件的确是以'~'打头的,不分青红皂白地将'~'替换会使你 的程序无法打开这些文件。一般来说,从shell通过命令行或环境变量传递入程 序的文件名不须要进行替换,因为shell已经替你做好,而程序自己生成的、用 户输入的,或从配置文件中读取的却应该进行替换。

这里是一段用标准string类的C++实现:

   string expand_path(const string& path)
   {
       if (path.length() == 0 || path[0] != '~')
         return path;
  
       const char *pfx = NULL;
       string::size_type pos = path.find_first_of('/');
  
       if (path.length() == 1 || pos == 1)
       {
           pfx = getenv("HOME");
           if (!pfx)
           {
               // 我们想替换"~/",但$HOME却没有设置
               struct passwd *pw = getpwuid(getuid());
               if (pw)
                 pfx = pw->pw_dir;
           }
       }
       else
       {
           string user(path,1,(pos==string::npos) ? string::npos : pos-1);
           struct passwd *pw = getpwnam(user.c_str());
           if (pw)
             pfx = pw->pw_dir;
       }
       // 如果我们不能找到能替换的选择,则将path返回
  
       if (!pfx)
         return path;
  
       string result(pfx);
  
       if (pos == string::npos)
         return result;
  
       if (result.length() == 0 || result[result.length()-1] != '/')
         result += '/';
  
       result += path.substr(pos+1);
  
       return result;
   }