How to get a file path to the program invoked?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
32 messages Options
12
Reply | Threaded
Open this post in threaded view
|

How to get a file path to the program invoked?

dokondr
Hi,
When my program starts it needs to know a complete path to the directory from which it was invoked.
In terms of standard shell (sh) I need the Haskell function that will do equivalent to:

#!/bin/sh
path=$(dirname $0)

How to get this path in Haskell?

getProgName :: IO String
defined
System.Environment only returns a file name of the program without its full path.

Thanks!

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: How to get a file path to the program invoked?

Simon Hengel-3
> How to get this path in Haskell?
Maybe FindBin or executable-path work.

Cheers,
Simon

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: How to get a file path to the program invoked?

Felipe Lessa
In reply to this post by dokondr
On Thu, Dec 1, 2011 at 2:12 PM, dokondr <[hidden email]> wrote:

> Hi,
> When my program starts it needs to know a complete path to the directory
> from which it was invoked.
> In terms of standard shell (sh) I need the Haskell function that will do
> equivalent to:
>
> #!/bin/sh
> path=$(dirname $0)
>
> How to get this path in Haskell?

If I understand you correctly, you want

  takeDirectory `fmap` getProgName

where

  import System.FilePath (takeDirectory)

Cheers,

--
Felipe.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: How to get a file path to the program invoked?

Simon Hengel-3
> > How to get this path in Haskell?
>
> If I understand you correctly, you want
>
>   takeDirectory `fmap` getProgName

I think getProgName does not give you the full path, but only the
program name.

Cheers,
Simon

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: How to get a file path to the program invoked?

Felipe Lessa
On Thu, Dec 1, 2011 at 3:41 PM, Simon Hengel <[hidden email]> wrote:
>> > How to get this path in Haskell?
>>
>> If I understand you correctly, you want
>>
>>   takeDirectory `fmap` getProgName
>
> I think getProgName does not give you the full path, but only the
> program name.

Neither does $0, does it?  It depends on how the program is called.

You can always use System.Directory.getCurrentDirectory with
System.FilePath.{isRelative,replaceDirectory} if you somehow need the
full path.  Note, however, that not even this is generally guaranteed
to be correct.

Cheers,

--
Felipe.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: How to get a file path to the program invoked?

Simon Hengel-3
On Thu, Dec 01, 2011 at 03:53:37PM -0200, Felipe Almeida Lessa wrote:

> On Thu, Dec 1, 2011 at 3:41 PM, Simon Hengel <[hidden email]> wrote:
> >> > How to get this path in Haskell?
> >>
> >> If I understand you correctly, you want
> >>
> >>   takeDirectory `fmap` getProgName
> >
> > I think getProgName does not give you the full path, but only the
> > program name.
>
> Neither does $0, does it?  It depends on how the program is called.
$0 depend everything you need to find your program (say, the relative or
absolute path used), but getProgName does not.  Here is an example:

    ./foo/foo

Here $0 will be "./foo/foo", but getProgName will be "foo".

Cheers,
Simon

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: How to get a file path to the program invoked?

Simon Hengel-3
On Thu, Dec 01, 2011 at 07:02:09PM +0100, Simon Hengel wrote:

> On Thu, Dec 01, 2011 at 03:53:37PM -0200, Felipe Almeida Lessa wrote:
> > On Thu, Dec 1, 2011 at 3:41 PM, Simon Hengel <[hidden email]> wrote:
> > >> > How to get this path in Haskell?
> > >>
> > >> If I understand you correctly, you want
> > >>
> > >>   takeDirectory `fmap` getProgName
> > >
> > > I think getProgName does not give you the full path, but only the
> > > program name.
> >
> > Neither does $0, does it?  It depends on how the program is called.
> $0 depend everything you need to find your program (say, the relative or
> absolute path used), but getProgName does not.  Here is an example:
>
>     ./foo/foo
>
> Here $0 will be "./foo/foo", but getProgName will be "foo".
s/depend/contains

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: How to get a file path to the program invoked?

dokondr
In reply to this post by Felipe Lessa
System.Directory.getCurrentDirectory does not solve the problem.
System.Directory.getCurrentDirectory returns the directory *from which* the program was called, also called "working directory".
The directory *from which* the program was called is not the same that the directory *where the program executable is*, which my program needs to know.
For example:
/opt/myApp/test/myProg  - is a program
One may call it in many ways:
1)
cd /opt/myApp/test/
./myProg
Current or working directory: ./

or:

2)
cd /usr/local 
/opt/myApp/test/myProg
Current or working directory: /usr/local

On the contrary, standard shell variable $0 - contains a full path to the program location in the directory structure, no matter from what directory the program was called.

How to find this path using GHC libraries? 


On Thu, Dec 1, 2011 at 8:53 PM, Felipe Almeida Lessa <[hidden email]> wrote:

Neither does $0, does it?  It depends on how the program is called.

You can always use System.Directory.getCurrentDirectory with
System.FilePath.{isRelative,replaceDirectory} if you somehow need the
full path.  Note, however, that not even this is generally guaranteed
to be correct.

Cheers,

--
Felipe.



--
All the best,
Dmitri O. Kondratiev

"This is what keeps me going: discovery"
[hidden email]
http://sites.google.com/site/dokondr/welcome



_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: How to get a file path to the program invoked?

dokondr
To be precise, $0 always contains the path to the program called. You are right, this path will change depending on location from which the program was called. So $0 is OK for my case, while current directory  is unrelated.

Try this:

#!/bin/sh                                                                                                            
echo "Arg 0: $0"
echo "All Parameters:  [$@]"
 
Again, any way to get the same functionality in GHC?


On Thu, Dec 1, 2011 at 10:32 PM, Giovanni Tirloni <[hidden email]> wrote:
On Thu, Dec 1, 2011 at 5:26 PM, dokondr <[hidden email]> wrote:
On the contrary, standard shell variable $0 - contains a full path to the program location in the directory structure, no matter from what directory the program was called.


Are you sure?

$ zero.sh
./zero.sh

$ ./zero.sh
./zero.sh

$ /home/gtirloni/zero.sh
/home/gtirloni/zero.sh



--
Giovanni






_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: How to get a file path to the program invoked?

Brandon Allbery
In reply to this post by dokondr
On Thu, Dec 1, 2011 at 14:26, dokondr <[hidden email]> wrote:
On the contrary, standard shell variable $0 - contains a full path to the program location in the directory structure, no matter from what directory the program was called

If the shell found it by $PATH search, $0 will be simply the program name with no directory and you will have to repeat the PATH search yourself.  (And the pathological case:  the user did "PATH=something yourprog", where "something" does not contain the directory holding "yourprog".)

There is no 100% reliable way to get the executable without using something like /proc/self/exe (only on Linux).

--
brandon s allbery                                      [hidden email]
wandering unix systems administrator (available)     (412) 475-9364 vm/sms


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: How to get a file path to the program invoked?

Anton Nikishaev
In reply to this post by dokondr
dokondr <[hidden email]> writes:

> Hi,
> When my program starts it needs to know a complete path to the directory from
> which it was invoked.
> In terms of standard shell (sh) I need the Haskell function that will do
> equivalent to:
>
> #!/bin/sh
> path=$(dirname $0)
>
> How to get this path in Haskell?
>
> getProgName :: IO String
> defined System.Environment only returns a file name of the program
> without its full path.
>
> Thanks!

http://hackage.haskell.org/package/system-argv0-0.1



--
cheers!
lelf                                       xmpp:[hidden email]


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: How to get a file path to the program invoked?

Alexey Khudyakov
In reply to this post by dokondr
On 01.12.2011 23:47, dokondr wrote:
> To be precise, $0 always contains the path to the program called. You
> are right, this path will change depending on location from which the
> program was called. So $0 is OK for my case, while current directory  is
> unrelated.
>
Actually it contains whatever was passed to exec. By convention this is
program name but it could be anything

#include <stdio.h>
#include <unistd.h>

int main(int argc, char** argv)
{
     if( argc != 1 ) {
         printf("%i: %s\n", argc, argv[0] );
     } else {
         execl("./argv","Random junk","",0);
     }
     return 0;
}

$ gcc argv.c -o argv && ./argv
2: Random junk



> Try this:
>
> #!/bin/sh
> echo "Arg 0: $0"
> echo "All Parameters:  [$@]"
>
> Again, any way to get the same functionality in GHC?
>
getArgs and getProgName should do the trick

http://hackage.haskell.org/packages/archive/base/latest/doc/html/System-Environment.html

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: How to get a file path to the program invoked?

Anton Nikishaev
In reply to this post by Anton Nikishaev
Anton Nikishaev <[hidden email]> writes:

> dokondr <[hidden email]> writes:
>
>> Hi, When my program starts it needs to know a complete path to the
>> directory from which it was invoked.  In terms of standard shell (sh)
>> I need the Haskell function that will do equivalent to:
>>
>> #!/bin/sh
>> path=$(dirname $0)
>>
>> How to get this path in Haskell?
>>
>> getProgName :: IO String
>> defined System.Environment only returns a file name of the program
>> without its full path.
>>
>> Thanks!
>
> http://hackage.haskell.org/package/system-argv0-0.1

(which is argv[0], and surely it's not always the “complete path to the
directory from which it was invoked”. $0 is not either.)



--
lelf                                       xmpp:[hidden email]


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: How to get a file path to the program invoked?

dokondr
In reply to this post by dokondr
Balazs,  thanks!
It's great that these packages exist!


On Thu, Dec 1, 2011 at 11:17 PM, Balazs Komuves <[hidden email]> wrote:

Hello,

I'm not subscribed to haskell cafe, but I browse the archives sometimes.

As Simon Hengel wrote there, there are two packages on Hackage
trying to solve this exact problem (since GHC and the standard library
does not provide the necessary information):

http://hackage.haskell.org/package/executable-path
http://hackage.haskell.org/package/FindBin

(Hackage is down at the moment, so I'm not completely sure about the second link).
I'm the author of the first one.

Balazs






_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: How to get a file path to the program invoked?

wren ng thornton
In reply to this post by dokondr
On 12/1/11 11:12 AM, dokondr wrote:
> Hi,
> When my program starts it needs to know a complete path to the directory
> from which it was invoked.
> In terms of standard shell (sh) I need the Haskell function that will do
> equivalent to:
>
> #!/bin/sh
> path=$(dirname $0)

That's not the path to the directory from which the script is invoked
(aka, $PWD or, more accurately, the results of `pwd`). That's the path
to the directory containing the script.

The current working directory (the dir from which the program is
invoked, provided the program haven't moved since invocation) can be
gotten by System.Directory.getCurrentDirectory in the directory package.

Getting the path to the location of the executable is trickier business.

--
Live well,
~wren

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: How to get a file path to the program invoked?

wren ng thornton
In reply to this post by dokondr
On 12/1/11 2:26 PM, dokondr wrote:
> How to find this path using GHC libraries?

There was a discussion about this recently over on libraries@, IIRC. The
short answer is that, at present, there is no function to give you $0.
We'd like to add such a function, but it's not been done yet.

Part of the problem is that, as Alexey says, the first element of argv
is just whatever is passed to exec, which is not guaranteed to be a
complete path, a canonical path, or any other specific thing we'd
desire. It's not at all straightforward to determine the actual location
of the executable, especially not in a platform-independent manner.
argv[0] can't be trusted, scanning through $PATH isn't guaranteed to
find it (and even if you find something of the right name, it's not
guaranteed to be the correct executable), etc etc.

--
Live well,
~wren

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: How to get a file path to the program invoked?

Donn Cave-4
Quoth wren ng thornton <[hidden email]>,

> There was a discussion about this recently over on libraries@, IIRC. The
> short answer is that, at present, there is no function to give you $0.
> We'd like to add such a function, but it's not been done yet.
>
> Part of the problem is that, as Alexey says, the first element of argv
> is just whatever is passed to exec, which is not guaranteed to be a
> complete path, a canonical path, or any other specific thing we'd
> desire. It's not at all straightforward to determine the actual location
> of the executable, especially not in a platform-independent manner.
> argv[0] can't be trusted, scanning through $PATH isn't guaranteed to
> find it (and even if you find something of the right name, it's not
> guaranteed to be the correct executable), etc etc.

This isn't your problem, though.

I mean, if the proposed function is to return the path to the executable
file, then indeed you have a big problem with argv[0].  argv[0] can be
anything - or nothing (it can be a null string.)

But if we've turned to the question of whether to return argv[0],
that's much simpler:  you don't need to consider why a programmer
might want it.  It's appalling to think that library developers
would withhold access to standard POSIX 1003.1 features while they
decide whether they approve of them.

        Donn

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: How to get a file path to the program invoked?

paul r-2
In reply to this post by dokondr
dokondr> On the contrary, standard shell variable $0 - contains a full
dokondr> path to the program location in the directory structure, no
dokondr> matter from what directory the program was called.

I don't think the comparison makes sense, as shell script invocation and
executable run are very different mechanisms. Whenever you invoke
a shell script, what really happens is that a program in your path (sh,
bash ...) gets started with an argument that is the path to the script
to load (your script actually). In this situation, you understand that
it is easy to provide the path to the script (the $0) : it is just the
file that the interpreter is loading.

I don't know if it is possible at all to get this information in the
context of binary execution. And I'm not sure it is a good practice
anyway :)

--
  Paul

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: How to get a file path to the program invoked?

Richard A. O'Keefe
In reply to this post by wren ng thornton

On 4/12/2011, at 7:32 PM, wren ng thornton wrote:
> Part of the problem is that, as Alexey says, the first element of argv is just whatever is passed to exec, which is not guaranteed to be a complete path, a canonical path, or any other specific thing we'd desire. It's not at all straightforward to determine the actual location of the executable, especially not in a platform-independent manner. argv[0] can't be trusted, scanning through $PATH isn't guaranteed to find it (and even if you find something of the right name, it's not guaranteed to be the correct executable), etc etc.

In particular, with posix_spawnp(), the $PATH that is used to find the executable
and the $PATH in the environment that the executable starts with can be two different things.


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: How to get a file path to the program invoked?

scooter.phd@gmail.com
In reply to this post by paul r-2
It's not a poor practice at all. Example: gcc, which uses the executable's path as the base directory from which other files are located. MacOS also does something similar.


-----Original message-----
From: Paul R <[hidden email]>
To:
dokondr <[hidden email]>
Cc:
Simon Hengel <[hidden email]>, haskell-cafe <[hidden email]>
Sent:
Sun, Dec 4, 2011 15:26:28 PST
Subject:
Re: [Haskell-cafe] How to get a file path to the program invoked?

dokondr> On the contrary, standard shell variable $0 - contains a full
dokondr> path to the program location in the directory structure, no
dokondr> matter from what directory the program was called.

I don't think the comparison makes sense, as shell script invocation and
executable run are very different mechanisms. Whenever you invoke
a shell script, what really happens is that a program in your path (sh,
bash ...) gets started with an argument that is the path to the script
to load (your script actually). In this situation, you understand that
it is easy to provide the path to the script (the $0) : it is just the
file that the interpreter is loading.

I don't know if it is possible at all to get this information in the
context of binary execution. And I'm not sure it is a good practice
anyway :)

--
Paul

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
12