Dup Ver Goto 📝

TidyPath

PT2/lang/cpp/random does not exist
To
146 lines, 439 words, 3391 chars Page 'TidyPath' does not exist.

This takes the PATH environment variable and filters out duplicates and nonexistent directories. (I originally used a Perl script, but rewrote in c++ for speed.)

#include <iostream>
#include <set>
#include <unordered_set>
#include <string>
#include <vector>
#include <sstream>
#include <iterator>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

using namespace std;

bool exists(const string& s) {
  const char* a = s.c_str();
  struct stat statbuf;
  if( stat(a,&statbuf) == 0 ) return true;
  return false;
}

vector<string> split(const string& str, const string& delim)
{
    vector<string> tokens;
    size_t prev = 0, pos = 0;
    do
    {
        pos = str.find(delim, prev);
        if (pos == string::npos) pos = str.length();
        string token = str.substr(prev, pos-prev);
        if (!token.empty()) tokens.push_back(token);
        prev = pos + delim.length();
    }
    while (pos < str.length() && prev < str.length());
    return tokens;
}

bool compstr(const char* a, const char* b, int l) {
  int i;
  for( i=0; i<l; i++ ) {
    if( a[i] != b[i] ) return false;
  }
  return true;
}

int main(int argc, char *argv[], char *envp[]) {
  char* path = nullptr;
  while(*envp) {
    if( compstr(*envp,"PATH=",5) ) {
      path = *envp;
      break;
    }
    envp++;
  }
  if( path != nullptr ) {
    path += 5;
    unordered_set<string> xs;
    vector<string> pcs = split(path,":");
    vector<string> npath;
    for( auto s : pcs ) {
      if( xs.count(s) == 0 ) {
        if( exists(s) ) {
          npath.push_back(s);
        }
        xs.insert(s);
      }
    }
    const char* const delim = ":";
    ostringstream imploded;
    copy(npath.begin(), npath.end(),
           ostream_iterator<string>(imploded, delim));
    cout << imploded.str() << "\n";
  } else {
    cerr << "no path" << endl;
  }
}

Filterpath

A slight more general variation of the above, this takes path components on the command line.

#include <iostream>
#include <set>
#include <unordered_set>
#include <string>
#include <vector>
#include <sstream>
#include <iterator>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

using namespace std;

bool exists(const string& s) {
  const char* a = s.c_str();
  return false;
}

vector<string> split(const string& str, const string& delim)
{
    vector<string> tokens;
    size_t prev = 0, pos = 0;
    do
    {
        pos = str.find(delim, prev);
        if (pos == string::npos) pos = str.length();
        string token = str.substr(prev, pos-prev);
        if (!token.empty()) tokens.push_back(token);
        prev = pos + delim.length();
    }
    while (pos < str.length() && prev < str.length());
    return tokens;
}

int main(int argc, char *argv[]) {
  const char* const delim = ":";
  unordered_set<string> xs;
  vector<string> npath;
  struct stat statbuf;
  for(int i=1; i<argc; i++) {
    vector<string> pcs = split(argv[i],delim);
    for( auto s : pcs ) {
      if( xs.count(s) == 0 ) {
        if( stat(s.c_str(),&statbuf) == 0 ) {
          npath.push_back(s);
        }
        xs.insert(s);
      }
    }
  }
  ostringstream imploded;
  copy(npath.begin(), npath.end(),
          ostream_iterator<string>(imploded, delim));
  string result = imploded.str();
  if( result.length() == 0 ) return 0;
  result = result.substr(0,result.length()-1);
  cout << result << "\n";
}