Need help with relative file path

Discussion in 'C++' started by Thomas Børlum, Jun 21, 2008.

  1. Hey all,

    I'm writing a c++ program that needs to read a file. I'm trying to read
    a file that is in the same directory as the executable.

    Everything works fine if I execute the program while in the program's
    directory. What I need to do is read that file regardless of where
    (cwd) I execute the program from, without hardcoding the absolute since
    the program might be moved or be in differant locations on other
    computers.

    What should I do?

    PS. I'm using the boost filesystem framework if it helps.
     
    Thomas Børlum, Jun 21, 2008
    #1
    1. Advertising

  2. Thomas Børlum

    Martin York Guest

    On Jun 21, 8:11 am, Thomas Børlum <> wrote:
    > Hey all,
    >
    > I'm writing a c++ program that needs to read a file. I'm trying to read
    > a file that is in the same directory as the executable.
    >
    > Everything works fine if I execute the program while in the program's
    > directory. What I need to do is read that file regardless of where
    > (cwd) I execute the program from, without hardcoding the absolute since
    > the program might be moved or be in differant locations on other
    > computers.
    >
    > What should I do?
    >
    > PS. I'm using the boost filesystem framework if it helps.


    Most OS's will give you the command used to execute your program in
    argv[0]
    This will usually include the path

    int main(int argc,char* argv[])
    {
    std::cout << argv[0] << "\n\n";
    }

    NB. It may be absolute or relative.
     
    Martin York, Jun 21, 2008
    #2
    1. Advertising

  3. Martin York wrote:
    > Most OS's will give you the command used to execute your program in
    > argv[0]
    > This will usually include the path


    Actually it's rather usual that argv[0] is simply what you wrote in
    the command line as the program's name, without any additions.
     
    Juha Nieminen, Jun 21, 2008
    #3
  4. On 2008-06-21 17:50:33 +0200, Martin York <> said:

    > On Jun 21, 8:11 am, Thomas Børlum <> wrote:
    >> Hey all,
    >>
    >> I'm writing a c++ program that needs to read a file. I'm trying to read
    >> a file that is in the same directory as the executable.
    >>
    >> Everything works fine if I execute the program while in the program's
    >> directory. What I need to do is read that file regardless of where
    >> (cwd) I execute the program from, without hardcoding the absolute since
    >> the program might be moved or be in differant locations on other
    >> computers.
    >>
    >> What should I do?
    >>
    >> PS. I'm using the boost filesystem framework if it helps.

    >
    > Most OS's will give you the command used to execute your program in
    > argv[0]
    > This will usually include the path
    >
    > int main(int argc,char* argv[])
    > {
    > std::cout << argv[0] << "\n\n";
    > }
    >
    > NB. It may be absolute or relative.


    Thanks that got me on the right track. I've done the following:

    path program_path(string(argv[0]) + "/..");
    program_path = complete(program_path);
    string settings_file = program_path.string() + "/settings.txt";

    works great.
     
    Thomas Børlum, Jun 21, 2008
    #4
  5. Thomas Børlum

    James Kanze Guest

    On Jun 21, 5:50 pm, Martin York <> wrote:
    > On Jun 21, 8:11 am, Thomas Børlum <> wrote:
    > > I'm writing a c++ program that needs to read a file. I'm
    > > trying to read a file that is in the same directory as the
    > > executable.


    > > Everything works fine if I execute the program while in the
    > > program's directory. What I need to do is read that file
    > > regardless of where (cwd) I execute the program from,
    > > without hardcoding the absolute since the program might be
    > > moved or be in differant locations on other computers.


    > > What should I do?


    > > PS. I'm using the boost filesystem framework if it helps.


    > Most OS's will give you the command used to execute your
    > program in argv[0] This will usually include the path


    First, of course: I'm not sure what you mean by "most OS's", but
    Unix certainly doesn't, and IIRC, nor does Windows. Unix, at
    any rate, gives you whatever the invoking program decides.
    (Note that this is NOT conform to the C or C++ standards;
    strictly speaking, a conforming implementation of C or C++ is
    impossible under Unix, and I'm pretty sure under Windows as
    well.)

    Secondly, of course, it's quite exceptional, both under Unix and
    under Windows, for the invoking command to include the path.
    In these two systems, the actual path is normally obtained from
    an environment variable.

    > int main(int argc,char* argv[])
    > {
    > std::cout << argv[0] << "\n\n";
    > }


    > NB. It may be absolute or relative.


    Most of the time, it's relative from some arbitrary entry in the
    PATH environment variable.

    I've encountered this problem several times in the past; at
    least under Unix, there is no possible solution from within the
    program.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jun 22, 2008
    #5
  6. Thomas Børlum

    James Kanze Guest

    On Jun 21, 6:21 pm, Juha Nieminen <> wrote:
    > Martin York wrote:
    > > Most OS's will give you the command used to execute your program in
    > > argv[0]
    > > This will usually include the path


    > Actually it's rather usual that argv[0] is simply what you
    > wrote in the command line as the program's name, without any
    > additions.


    That's more or less what the standard requires. Under Unix, of
    course, this only works if the shell used to start the command
    collaborates (most do). And it leaves open the question as to
    what should be in argv[0] if the command is not started from the
    command line, but from some other program.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jun 22, 2008
    #6
  7. James Kanze wrote:
    > On Jun 21, 6:21 pm, Juha Nieminen <> wrote:
    >> Martin York wrote:
    >>> Most OS's will give you the command used to execute your program in
    >>> argv[0]
    >>> This will usually include the path

    >
    >> Actually it's rather usual that argv[0] is simply what you
    >> wrote in the command line as the program's name, without any
    >> additions.

    >
    > That's more or less what the standard requires. Under Unix, of
    > course, this only works if the shell used to start the command
    > collaborates (most do). And it leaves open the question as to
    > what should be in argv[0] if the command is not started from the
    > command line, but from some other program.


    Also, if I'm not mistaken, the C standard doesn't actually guarantee
    that argv[0] will contain anything at all (although I don't remember if
    that means that argv[0] could actually be a null pointer, or if it
    simply means that it points to an empty string).

    I assume the C++ standard inherits the same specification.
     
    Juha Nieminen, Jun 26, 2008
    #7
  8. Thomas Børlum

    emarcari Guest

    On Jun 21, 12:11 pm, Thomas Børlum <> wrote:
    > Hey all,
    >
    > I'm writing a c++ program that needs to read a file. I'm trying to read
    > a file that is in the same directory as the executable.
    >
    > Everything works fine if I execute the program while in the program's
    > directory. What I need to do is read that file regardless of where
    > (cwd) I execute the program from, without hardcoding the absolute since
    > the program might be moved or be in differant locations on other
    > computers.
    >
    > What should I do?
    >
    > PS. I'm using the boost filesystem framework if it helps.


    You may use getenv, doing something like this:
    std::string source_dir = getenv( "srcdir" );

    Look at http://www.cplusplus.com/reference/clibrary/cstdlib/getenv.html,
    that there are another examples.
     
    emarcari, Jun 26, 2008
    #8
  9. Thomas Børlum

    James Kanze Guest

    On Jun 26, 11:58 am, Juha Nieminen <> wrote:
    > James Kanze wrote:
    > > On Jun 21, 6:21 pm, Juha Nieminen <> wrote:
    > >> Martin York wrote:
    > >>> Most OS's will give you the command used to execute your
    > >>> program in argv[0] This will usually include the path


    > >> Actually it's rather usual that argv[0] is simply what you
    > >> wrote in the command line as the program's name, without any
    > >> additions.


    > > That's more or less what the standard requires. Under Unix, of
    > > course, this only works if the shell used to start the command
    > > collaborates (most do). And it leaves open the question as to
    > > what should be in argv[0] if the command is not started from the
    > > command line, but from some other program.


    > Also, if I'm not mistaken, the C standard doesn't actually
    > guarantee that argv[0] will contain anything at all (although
    > I don't remember if that means that argv[0] could actually be
    > a null pointer, or if it simply means that it points to an
    > empty string).


    > I assume the C++ standard inherits the same specification.


    It does, more or less. First, argc may be 0, in which case,
    argv[0] is guaranteed to be a null pointer (and accessing any
    other argv is undefined behavior). If argc is greater than 0,
    then "the string pointed to by argv[0] represents the program
    name; argv[0][0] shall be the null character if the program name
    is not available from the host environment." Note that this
    does NOT say that the implementation may unconditionally place
    an empty string in argv; it says that it may put an empty string
    there IF "the program name is not available from the host
    environment" (from the C standard), or ``argv[0] shall be the
    pointer to the initial character of a NTMBS that represents the
    name used to invoke the program or ""'' (from the C++ standard).

    Note that the C standard does not define what it means by
    "program name": is it the basename, the name as it appears in
    the command line, or the full pathname? The C++ standard is
    univocal: it must be the name as it appears in the command line.
    On the other hand, the C standard requires the name, if it is
    available; the C++ standard leaves it up to the implementation.
    (The reason that I bring up the C standard here is that I
    imagine most implementations will use common code for this,
    whether main is in C or in C++, and so should be conform to both
    standards.)

    Of course, this requirement is ignored more often than it is
    met; Unix doesn't make the program name available in any shape,
    form or fashion, and I don't think Windows does either, so a
    conforming C or C++ implementation must, strictly speaking,
    always put an empty string in argv[0]. None do, at least that I
    know of, and Posix has a conflicting requirement that argv[0]
    actually contain a string specified by the program which starts
    your program (which calls the system function execv). All of
    the Unix shells I have handy under Solaris (sh, ksh and bash)
    *do* pass the name from the command line as argv[0], when
    starting a program, as does the default command interpreter
    under Windows. The bash in CygWin doesn't, however, and of
    course, if your program is started by some other tool, you're at
    the mercy of that tool. (I have no idea, for example, what
    you'll get if your program is started by clicking an icon on the
    desktop. Hopefully, whatever is present in the "Target:" field
    of the properties, but I have no way of verifying this.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jun 27, 2008
    #9
  10. Thomas Børlum

    James Kanze Guest

    On Jun 26, 2:13 pm, emarcari <> wrote:
    > On Jun 21, 12:11 pm, Thomas Børlum <> wrote:
    > > I'm writing a c++ program that needs to read a file. I'm
    > > trying to read a file that is in the same directory as the
    > > executable.


    > > Everything works fine if I execute the program while in the
    > > program's directory. What I need to do is read that file
    > > regardless of where (cwd) I execute the program from,
    > > without hardcoding the absolute since the program might be
    > > moved or be in differant locations on other computers.


    > > What should I do?


    > > PS. I'm using the boost filesystem framework if it helps.


    > You may use getenv, doing something like this:
    > std::string source_dir = getenv( "srcdir" );


    Don't ever write something like this. It will generally crash,
    since getenv returns a null pointer if the specified variable
    isn't set (and "srcdir" generally isn't).

    With regards to obtaining the full pathname of the executable,
    something like this depends on whoever starts the executable
    setting the appropriate variable. Bash sets "_" to the full
    path name, but I don't know of any other program which sets
    anything, so unless you can guarantee that your program will
    only be started by bash, you can't use this.

    > Look at
    > http://www.cplusplus.com/reference/clibrary/cstdlib/getenv.html,
    > that there are another examples.


    Which very clearly says that getenv may return a null pointer,
    so it cannot be used as an initializer for a string.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jun 27, 2008
    #10
  11. Thomas Børlum

    James Kanze Guest

    On Jun 27, 7:15 pm, Paavo Helde <> wrote:
    > "Alf P. Steinbach" <> kirjutas:
    > > * James Kanze:

    > [...]
    > >> Of course, this requirement is ignored more often than it
    > >> is met; Unix doesn't make the program name available in any
    > >> shape, form or fashion, and I don't think Windows does
    > >> either,


    > > Huh?


    > From Windows SDK documentation:


    > LPTSTR WINAPI GetCommandLine(void);


    > The return value is a pointer to the command-line string for
    > the current process.


    And when the process wasn't started from a command line?

    > ...
    > Note The name of the executable in the command line that the
    > operating system provides to a process is not necessarily
    > identical to that in the command line that the calling process
    > gives to the CreateProcess function. The operating system may
    > prepend a fully qualified path to an executable name that is
    > provided without a fully qualified path.


    > So it seems Windows makes it available in some shape or
    > fashion ;-)


    I seem to recall experimenting at one time with Windows, and
    seeing exactly the behavior I got from Unix. And if I
    understand the documentation of CreateProcess correctly, if I
    call it with something like:

    CreateProcess( "C:\\Hidden\\even more hidden\\myProg.exe",
    "C:\\Documents and Settings\\James Kanze\\...",
    // all the rest of the verbage...
    ) ;

    GetCommandLine is going to return the second string, which
    doesn't begin to give the slightest hint about where the actual
    executable is situated. (On the other hand, given the number of
    functions in the Windows interface, it wouldn't surprise me if
    there wasn't one to return the first argument to CreateProcess
    as well. And from the documentation, that might be enough.)

    In sum, it's exactly like the situation in Unix: if the invoking
    program collaborates (and the various command interpreters
    generally do), then it works, but everything depends on the
    invoking program.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jun 27, 2008
    #11
  12. Thomas Børlum

    Joe Greer Guest

    James Kanze <> wrote in news:c069673d-4ce6-401b-b340-
    :

    >
    > GetCommandLine is going to return the second string, which
    > doesn't begin to give the slightest hint about where the actual
    > executable is situated. (On the other hand, given the number of
    > functions in the Windows interface, it wouldn't surprise me if
    > there wasn't one to return the first argument to CreateProcess
    > as well. And from the documentation, that might be enough.)
    >


    GetModuleName() with a NULL will give you the exe-s name, but this
    digresses from the topic. :)

    joe
     
    Joe Greer, Jun 27, 2008
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Asad

    relative file path

    Asad, May 26, 2004, in forum: Java
    Replies:
    7
    Views:
    11,599
  2. Matt
    Replies:
    3
    Views:
    19,625
    Sudsy
    Jul 8, 2004
  3. Thomas Guettler
    Replies:
    3
    Views:
    772
    Andrei
    Oct 27, 2003
  4. Oren
    Replies:
    1
    Views:
    558
    Michael D. Ober
    Apr 29, 2007
  5. Nigel Wilkinson
    Replies:
    2
    Views:
    399
    Nigel Wilkinson
    Jul 25, 2005
Loading...

Share This Page