# Search path for executable

**URL:** <https://discourse.julialang.org/t/search-path-for-executable/3511>\
**Category:** General Usage\
**Tags:** question\
**Created:** [May 4, 2017, 11:15am UTC](https://discourse.julialang.org/t/search-path-for-executable/3511 "2017-05-04T11:15:55Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [May 4, 2017, 11:15am UTC](https://discourse.julialang.org/t/search-path-for-executable/3511/1 "2017-05-04T11:15:55Z")

</div>

Is there a more or less portable way of getting the path of an executable if available? When `is_unix()`, I guess something like

```julia
function find_in_path(program)
    try chomp(readstring(`which $program`))
    catch
        nothing
    end
end

```

works, but I don’t know how to deal with `is_windows()`.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [May 4, 2017, 11:38am UTC](https://discourse.julialang.org/t/search-path-for-executable/3511/2 "2017-05-04T11:38:38Z")

</div>

On Windows `which` is `where`

---

<div class="post-metadata">

**Author:** ![mzaffalon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mzaffalon/32/214168_2.png) [@mzaffalon](https://discourse.julialang.org/u/mzaffalon)\
**Post date:** [May 4, 2017, 11:38am UTC](https://discourse.julialang.org/t/search-path-for-executable/3511/3 "2017-05-04T11:38:43Z")

</div>

It seems that `where.exe` is the equivalent.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [May 4, 2017, 11:51am UTC](https://discourse.julialang.org/t/search-path-for-executable/3511/4 "2017-05-04T11:51:56Z")

</div>

I am not a Windows user, but from googling it looks like `where` on Windows is closer to `locate` on Unix (searches the whole filesystem, not only executables).

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [May 4, 2017, 1:33pm UTC](https://discourse.julialang.org/t/search-path-for-executable/3511/5 "2017-05-04T13:33:26Z")

</div>

If `PATH` environment variable is correctly set on Windows, this should work on any system:

```julia
function foo(exec)
    for dir in split(ENV["PATH"], @static is_windows() ? ";" : ":")
        if isdir(dir) && exec in readdir(dir)
            return joinpath(dir, exec)
        end
    end
    return ""
end

```

This is more or less what `which` does (you should also check that the file is actually executable)

---

<div class="post-metadata">

**Author:** ![tkelman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkelman/32/692_2.png) [@tkelman](https://discourse.julialang.org/u/tkelman)\
**Post date:** [May 4, 2017, 1:34pm UTC](https://discourse.julialang.org/t/search-path-for-executable/3511/6 "2017-05-04T13:34:20Z")

</div>

And be aware that `which` isn’t guaranteed to be present in minimal linux environments like some docker containers

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [May 4, 2017, 3:39pm UTC](https://discourse.julialang.org/t/search-path-for-executable/3511/7 "2017-05-04T15:39:05Z")

</div>

Thanks for the solution.

> [@giordano](#):
>
> should also check that the file is actually executable

How can I do that? I found `uperm` etc, but I could not figure out the user’s `uid`.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [May 4, 2017, 4:14pm UTC](https://discourse.julialang.org/t/search-path-for-executable/3511/8 "2017-05-04T16:14:09Z")

</div>

In order to check if the file is executable by the owner, you can do this:

```julia
function foo(exec)
    for dir in split(ENV["PATH"], @static is_windows() ? ";" : ":")
        if isdir(dir) && exec in readdir(dir)
            file = joinpath(dir, exec)
            if isfile(file) && (uperm(file) & 0x01 > 0)
                return file
            end
        end
    end
    return ""
end

```

I also added the test that the file is a regular file, also directory are executable.

But maybe you want to determine if it’s executable by the current user? Note that `which` uses `-x` which doesn’t check if current user can run the program. For example, with both bash and dash, on my system:

```julia
$ [-x /sbin/ifconfig] && echo "Yes, we can" || echo "No, we can't"
Yes, we can

```

even if my user can’t run that program.

---

<div class="post-metadata">

**Author:** ![musm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/musm/32/3675_2.png) [@musm](https://discourse.julialang.org/u/musm)\
**Post date:** [May 5, 2017, 10:29pm UTC](https://discourse.julialang.org/t/search-path-for-executable/3511/9 "2017-05-05T22:29:13Z")

</div>

> [@giordano](#):
>
> But maybe you want to determine if it’s executable by the current user? Note that which uses -x which doesn’t check if current user can run the program. For example, with both bash and dash, on my system:

Alternatively this would also work

```julia
try success(`exe`)
catch
    error("exe not found")
end

```

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [May 14, 2017, 11:29pm UTC](https://discourse.julialang.org/t/search-path-for-executable/3511/10 "2017-05-14T23:29:37Z")

</div>

> [@musm](#):
>
> Alternatively this would also work
> 
> ```julia
> try success(`exe`)
> catch
> error("exe not found")
> end
> 
> ```

I wouldn’t start a process just to see if my user can run it. For example, the [`yes` command](https://en.wikipedia.org/wiki/Yes_%28Unix%29) runs forever until it’s killed.

---

<div class="post-metadata">

**Author:** ![tkelman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkelman/32/692_2.png) [@tkelman](https://discourse.julialang.org/u/tkelman)\
**Post date:** [May 15, 2017, 12:53am UTC](https://discourse.julialang.org/t/search-path-for-executable/3511/11 "2017-05-15T00:53:24Z")

</div>

depending on the program, a -h, --help, -v, or --version flag would usually be safe to try. that doesn’t help you locate it, but can tell you if it’s on the path somewhere and the first one found is runnable.

---

<div class="post-metadata">

**Author:** ![musm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/musm/32/3675_2.png) [@musm](https://discourse.julialang.org/u/musm)\
**Post date:** [May 15, 2017, 3:15am UTC](https://discourse.julialang.org/t/search-path-for-executable/3511/12 "2017-05-15T03:15:58Z")

</div>

fair point but I think if you know in advance the exe you want to check it’s a simple and effective way especially if you do as tkelman suggestions and use it with a flag such at -h  
BTW  
with your script the `@static` is not necessary  
Also oddly enough this check:  
`uperm(file) & 0x01 > 0`  
fails for `exe` that I can actually execute on windows  
e.g. something as simple as  
“cmd.exe” fails with that check since it has permission `06` even thought it is executable

---

<div class="post-metadata">

**Author:** ![musm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/musm/32/3675_2.png) [@musm](https://discourse.julialang.org/u/musm)\
**Post date:** [May 18, 2017, 6:21pm UTC](https://discourse.julialang.org/t/search-path-for-executable/3511/13 "2017-05-18T18:21:34Z")

</div>

I like your script the following should be more robust

```julia
function foo(exec)
   if is_windows() && rsplit(exec, '.')[end] != "exe"
           exec *= ".exe"
    end
    for dir in split(ENV["PATH"], is_windows() ? ";" : ":")
        if isdir(dir) && exec in readdir(dir)
            file = joinpath(dir, exec)
            if isfile(file)
                if (uperm(file) & 0x01 > 0) || (if is_windows(); uperm(file) == 0x06 end)
                    return file
                end
            end
        end
    end
    return ""
end

```

such a function seems like a good candidate for inclusion in base

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [May 18, 2017, 6:23pm UTC](https://discourse.julialang.org/t/search-path-for-executable/3511/14 "2017-05-18T18:23:55Z")

</div>

Yeah, much better now 🙂

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [May 19, 2017, 6:39am UTC](https://discourse.julialang.org/t/search-path-for-executable/3511/15 "2017-05-19T06:39:45Z")

</div>

Perhaps you could make a PR, or at least open an issue.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [April 24, 2019, 11:58pm UTC](https://discourse.julialang.org/t/search-path-for-executable/3511/16 "2019-04-24T23:58:43Z")

</div>

For the record, now Julia has `Sys.which`:

```julia
julia> Sys.which("julia")
"/usr/bin/julia"

```
