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";
}