views:

283

answers:

6

In the interpreter for my programming languages I have to correctly handle the parts in case the import function is called. I then need to check if such a file is in the /libs folder (located at the same place as my executeable!) and if it doesn't exist I have to check in the directory of the current script.

  • How can I get the exact path to the directory where the executeable is located from argv?
  • What is the best way to remove the file from the end of a path, e.g:

    C:/a/b/c/file.exe should become C:/a/b/c/

+2  A: 
  1. There is no guaranteed way to do that. You can try looking in argv[0] but whether that has the full path or just the name of the binary depends on the platform and how your process was invoked.
  2. You can use strrchr to find the last slash and replace the character after it with '\0'

Code example:

// Duplicate the string so as not to trash the original
// You can skip this if you don't mind modifying the original data
// and the originald is writeable (i.e. no literal strings)
char *path = strdup(...);

char *last_slash = strrchr(path, '/');
if (last_slash)
{
#if PRESERVE_LAST_SLASH
    *(last_slash + 1) = '\0';
#else
    *last_slash = '\0';
#endif
}
R Samuel Klatchko
A: 

Scan backwards from the end of a string for the first '/' character.

Judge Maygarden
+2  A: 

A non-portable way on Linux (and maybe other *nix) would be to use readlink on /proc/self/exe if argv[0] doesn't contain the entire path.

nategoose
+1 nice platform specific technique.
R Samuel Klatchko
A: 

Not optimal, but works fine:

int main(int argc, char **argv) {
    using namespace std;
    char buffer[MAXPATHLEN];
    realpath(argv[0], buffer);
    string fullpath = buffer;
    fullpath = string(fullpath, 0, fullpath.rfind("/"));
    cout << fullpath << endl;
}

For relative path I'm using realpath(), which is unix/linux specific. For windows you could use GetModuleFileName(NULL, buffer, MAXPATHLEN), and of course the separator isn't the same.

jweyrich
+1  A: 

If your environment has the equivalent of PWD in the environment, you can just append /$argv[0] to it.

This might give you something you don't expect like /foo1/foo2/../foo3/ but that's ok. It's a valid path and can be globbed.

frankc
The working directory is usually different from the location of the executable.
Potatoswatter
This is incorrect. PWD is your working directory. If the program was found via PATH, it's location has nothing to do with the working directory.
R Samuel Klatchko
Or if it was found by the first line of an executable file. Or if the program was executed in ANY way besides `./my_prog`. Question states that this is an interpreter.
Potatoswatter
A: 

For Windows (non portable) use ::GetModuleFileName() and ::PathRemoveFileSpec():

TCHAR sPath[MAX_PATH] = {0};
if(::GetModuleFileName(NULL, sPath, MAX_PATH))
    ::PathRemoveFileSpec(sPath))
// sPath is the executable path if the module is an exe

cheers, AR

Alain Rist