How to get a file path to the program invoked?

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!

On Thu, Dec 1, 2011 at 2:12 PM, 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?
If I understand you correctly, you want takeDirectory `fmap` getProgName where import System.FilePath (takeDirectory) Cheers, -- Felipe.

On Thu, Dec 1, 2011 at 3:41 PM, Simon Hengel
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.

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
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

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
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

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 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"
dokondr@gmail.com
http://sites.google.com/site/dokondr/welcome

On Thu, Dec 1, 2011 at 14:26, dokondr
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 allbery.b@gmail.com wandering unix systems administrator (available) (412) 475-9364 vm/sms

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

Quoth wren ng thornton
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

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.

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
That's true even for regular fork/exec.
-----Original message-----
From: Richard O'Keefe

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

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

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!
http://hackage.haskell.org/package/system-argv0-0.1 -- cheers! lelf xmpp:nik_n@jabber.ru

Anton Nikishaev
dokondr
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!
(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:nik_n@jabber.ru

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

Hi I was running into a similar problem while working on GHC not long ago - short version is that it's not even possible to find out the executable path portably from C [1]. Using argv[0] just gave me the path of the GHC wrapper script, for example - as it uses exec without "-a". The whole thing is easiest if you're on Linux: getExePath = readSymbolicLink "/proc/self/exe" On all other operation system, one needs to start mucking around with custom kernel calls. Or, more realistically, try to find a way around requiring it... Greetings, Peter Wortmann [1] http://stackoverflow.com/questions/1023306

On Thu, Dec 15, 2011 at 09:48, Peter Wortmann
path portably from C [1]. Using argv[0] just gave me the path of the GHC wrapper script, for example - as it uses exec without "-a".
Note that "exec -a" is a bash-ism and not portable to POSIX shells (ash on *BSD, dash on Debian/Ubuntu, etc.) or traditional /bin/sh as still shipped with some commercial Unixes. -- brandon s allbery allbery.b@gmail.com wandering unix systems administrator (available) (412) 475-9364 vm/sms

On 16/12/2011, at 11:55 AM, Brandon Allbery wrote:
Note that "exec -a" is a bash-ism and not portable to POSIX shells
Recent versions of ksh also support this, so it's not just bash. But there are certainly a lot of POSIX shells that don't, including the version of ksh on my main machine.

May I ask what the problem is you're trying to solve?
If you want to access datafiles in an installed program then Cabal can
help you with that. See
http://www.haskell.org/cabal/users-guide/#accessing-data-files-from-package-...
If you want to do more complicated things, maybe take a look at how
GHC does it. For example, on OS X (and other Unix-based systems) the
"ghc" command is actually a script:
$ cat `which ghc`
#!/bin/sh
exedir="/Library/Frameworks/GHC.framework/Versions/7.0.3-x86_64/usr/lib/ghc-7.0.3"
exeprog="ghc-stage2"
executablename="$exedir/$exeprog"
datadir="/Library/Frameworks/GHC.framework/Versions/7.0.3-x86_64/usr/share"
bindir="/Library/Frameworks/GHC.framework/Versions/7.0.3-x86_64/usr/bin"
topdir="/Library/Frameworks/GHC.framework/Versions/7.0.3-x86_64/usr/lib/ghc-7.0.3"
pgmgcc="/Developer/usr/bin/gcc"
executablename="$exedir/ghc"
exec "$executablename" -B"$topdir" -pgmc "$pgmgcc" -pgma "$pgmgcc"
-pgml "$pgmgcc" -pgmP "$pgmgcc -E -undef -traditional" ${1+"$@"}
/ Thomas
On 1 December 2011 16:12, 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 Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Push the envelope. Watch it bend.
participants (12)
-
Anton Nikishaev
-
Brandon Allbery
-
dokondr
-
Donn Cave
-
Felipe Almeida Lessa
-
Paul R
-
Peter Wortmann
-
Richard O'Keefe
-
scooter.phd@gmail.com
-
Simon Hengel
-
Thomas Schilling
-
wren ng thornton