# \`file.choose()\` in \`Julia\`?

**URL:** <https://discourse.julialang.org/t/file-choose-in-julia/69703>\
**Category:** New to Julia\
**Tags:** filesystem, io, gui\
**Created:** [October 13, 2021, 5:15pm UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703 "2021-10-13T17:15:07Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [October 14, 2021, 7:27am UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/21 "2021-10-14T07:27:41Z")

</div>

How about `readdir()`?

---

<div class="post-metadata">

**Author:** ![Alex\_Tantos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex_tantos/32/10636_2.png) [@Alex\_Tantos](https://discourse.julialang.org/u/Alex_Tantos)\
**Post date:** [October 14, 2021, 8:09am UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/22 "2021-10-14T08:09:33Z")

</div>

Yesterday, I fiddled around with non-interactive alternatives to opening and reading file paths and I found out about `readdir()`, which is convenient, indeed, for getting and joining paths+files!  
But I also came across a package called `Glob` that does, well, `glob`bing. I ended up with the following two non-interactive lines of code for getting back, at least, filenames of a specific file type (.txt here) so that the search is limited. Not ideal, but at least saves some time if the directory is not huge. Any input or hint for improvement is more than welcome:

```julia
# with the Glob dependency
julia> using Glob
julia> glob(glob"*.txt", ".")
8-element Vector{String}:
 "./big_text.txt"
 "./exams.txt"
 "./intermediate_text.txt"
 "./new.txt"
 "./newtxt.txt"
 "./newtxt2.txt"
 "./small_text.txt"
 "./test.txt"

# no dependency - base Julia
julia> filter(str -> contains(str, r"\.txt"), readdir(join=true))
8-element Vector{String}:
 "/Users/atantos/Desktop/big_text.txt"
 "/Users/atantos/Desktop/exams.txt"
 "/Users/atantos/Desktop/intermediate_text.txt"
 "/Users/atantos/Desktop/new.txt"
 "/Users/atantos/Desktop/newtxt.txt"
 "/Users/atantos/Desktop/newtxt2.txt"
 "/Users/atantos/Desktop/small_text.txt"
 "/Users/atantos/Desktop/test.txt"

```

The benefit of being able to interactively select a directory through a GUI interface to get back the file path is that during daily tasks a (data) scientist-user can very easily browse the filesystem and find a specific file (whose name they don’t recall) that they want to open/read.

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [October 14, 2021, 9:08am UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/23 "2021-10-14T09:08:48Z")

</div>

> [@Alex\_Tantos](#):
>
> Any input or hint for improvement is more than welcome:

This takes it a step further:

```julia
using Glob
using REPL.TerminalMenus: request, RadioMenu
files = glob(glob"*.txt", ".")
file = files[request(RadioMenu(files))]

```

---

<div class="post-metadata">

**Author:** ![Alex\_Tantos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex_tantos/32/10636_2.png) [@Alex\_Tantos](https://discourse.julialang.org/u/Alex_Tantos)\
**Post date:** [October 14, 2021, 9:17am UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/24 "2021-10-14T09:17:53Z")

</div>

That is a big step @GunnarFarneback ! Thanks a lot! Interactiveness is partly achieved! @rafael.guerra this one is also for you!

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [October 14, 2021, 9:37am UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/25 "2021-10-14T09:37:56Z")

</div>

If you don’t need the extra functionality of glob,

```julia
files = filter(endswith(".txt"), readdir(; join=true))

```

does the same thing without the dependency. (Possibly worse performance, but you won’t be bottlenecked on this operation anyway)

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [October 14, 2021, 12:26pm UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/27 "2021-10-14T12:26:18Z")

</div>

> [@rafael.guerra](#):
>
> could be to add `basename` to display only the file names

That’s actually the default behaviour, `readdir("SubDir")` will return `"filename.ext"`, `readdir("SubDir"; join=true)` gives `"SubDir/filename.ext"` and `readdir(abspath("SubDir"); join=true)` gives `"/home/path/of/SubDir/filename.ext"`. So using `basename` is crossing the river for water.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [October 14, 2021, 12:28pm UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/28 "2021-10-14T12:28:21Z")

</div>

@gustaphe, thanks and nevermind. Will delete post.

---

<div class="post-metadata">

**Author:** ![suavesito](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/suavesito/32/34386_2.png) [@suavesito](https://discourse.julialang.org/u/suavesito)\
**Post date:** [October 15, 2021, 2:07am UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/29 "2021-10-15T02:07:10Z")

</div>

> [@stevengj](#):
>
> wrap this library (or similar) in a JLL (binary package) and then write a Julia wrapper: [GitHub - mlabbe/nativefiledialog: A tiny, neat C library that portably invokes native file open and save dialogs.](https://github.com/mlabbe/nativefiledialog)

[JLL done](https://github.com/JuliaBinaryWrappers/NativeFileDialog_jll.jl)! I’m working on the wrapper. 😃

---

<div class="post-metadata">

**Author:** ![suavesito](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/suavesito/32/34386_2.png) [@suavesito](https://discourse.julialang.org/u/suavesito)\
**Post date:** [October 15, 2021, 2:10am UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/30 "2021-10-15T02:10:33Z")

</div>

> [@GunnarFarneback](#):
>
> ```julia
> using Glob
> using REPL.TerminalMenus: request, RadioMenu
> files = glob(glob"*.txt", ".")
> file = files[request(RadioMenu(files))]
> 
> ```

May I use this code to do a more advance terminal file picker?

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [October 15, 2021, 5:42am UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/31 "2021-10-15T05:42:35Z")

</div>

Of course, but you probably want to make a custom menu, so there wouldn’t be much left of these particular code lines. You can get some inspiration of what can be done with `REPL.TerminalMenus` from [https://github.com/GunnarFarneback/PackageCompatUI.jl](https://github.com/GunnarFarneback/PackageCompatUI.jl).

---

<div class="post-metadata">

**Author:** ![Alex\_Tantos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex_tantos/32/10636_2.png) [@Alex\_Tantos](https://discourse.julialang.org/u/Alex_Tantos)\
**Post date:** [October 15, 2021, 11:40am UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/32 "2021-10-15T11:40:30Z")

</div>

Looking forward to hearing more news on the wrapper!

---

<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:** [October 15, 2021, 12:09pm UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/33 "2021-10-15T12:09:45Z")

</div>

I did some very _quick_ experimentation, while waiting for @suavesito’s better wrapper:

```julia
using NativeFileDialog_jll

function choose_file()
    path = Ref(Ptr{UInt8}())
    r = @ccall libnfd.NFD_OpenDialog(C_NULL::Ptr{Cchar}, C_NULL::Ptr{Cchar}, path::Ref{Ptr{UInt8}})::Cint
    if r == 2
        # User clicked "Cancel"
        out = nothing
    elseif r == 1
        out = unsafe_string(path[])
    else
        error()
    end
    return out
end

```

This works fine on Linux, but it seems to be pretty buggy on macOS (you can’t select the file in the dialog until you press some random keys), I don’t know if it’s an upstream problem or what.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [October 15, 2021, 2:15pm UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/34 "2021-10-15T14:15:27Z")

</div>

@giordano, your magic works wonderfully on Win10.  
Thanks for sharing such a useful code.

This is the first time I’ve seen adding a C (?) library directly using the Julia package manager. Could you please comment on this or provide a link for further reading?

---

<div class="post-metadata">

**Author:** ![gbaraldi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gbaraldi/32/22101_2.png) [@gbaraldi](https://discourse.julialang.org/u/gbaraldi)\
**Post date:** [October 15, 2021, 2:19pm UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/35 "2021-10-15T14:19:00Z")

</div>

You just discovered \_jll packages and [GitHub - JuliaPackaging/BinaryBuilder.jl: Binary Dependency Builder for Julia](https://github.com/JuliaPackaging/BinaryBuilder.jl) . Lot’s of packages use C (and others langs such as fortran) dependencies and have these packages as dependencies and julia downloads the binaries automatically through the artifact system.

---

<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:** [October 15, 2021, 2:21pm UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/36 "2021-10-15T14:21:13Z")

</div>

> [@rafael.guerra](#):
>
> This is the first time I’ve seen adding a C (?) library directly using the Julia package manager.

You do all the time 🙂 It’s actually nice to see users aren’t even aware of it, I guess it means it works well.

For further information you can read [Pkg + BinaryBuilder -- The Next Generation](https://julialang.org/blog/2019/11/artifacts/) or watch the videos listed in [Home · BinaryBuilder.jl](https://docs.binarybuilder.org/stable/#Videos-and-tutorials). There will be also a talk about this, specifically about the integration of JLL packages with the package manager, in the upcoming [Packaging Conference](https://packaging-con.org/)

---

<div class="post-metadata">

**Author:** ![Alex\_Tantos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex_tantos/32/10636_2.png) [@Alex\_Tantos](https://discourse.julialang.org/u/Alex_Tantos)\
**Post date:** [October 15, 2021, 2:21pm UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/37 "2021-10-15T14:21:54Z")

</div>

Unfortunately, on mac it hangs…no error or warning or anything…

---

<div class="post-metadata">

**Author:** ![suavesito](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/suavesito/32/34386_2.png) [@suavesito](https://discourse.julialang.org/u/suavesito)\
**Post date:** [October 15, 2021, 6:45pm UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/38 "2021-10-15T18:45:26Z")

</div>

Hi @giordano, thanks for testing it, and also thanks for that testing code (I was having trouble understanding how to pass that double pointer…).

About Mac… [this](https://github.com/mlabbe/nativefiledialog/issues/86) issue is fixed [here](https://github.com/mlabbe/nativefiledialog/commit/eb29acc563cbb26390653bf3dc57a08d8f09074d) but (alongside other patches) it is in the `devel` branch.

If you (or someone else) can try to build that branch and tell me how it goes, the NativeFileDialog\_jll.jl can be change to the devel branch if it fixes the issue.

For building the branch on Mac and testing the complete code would be

```julia
$ git clone 'https://github.com/mlabbe/nativefiledialog'
$ cd nativefiledialog/src
$ git checout devel
$ cc nfd_cocoa.m nfd_common.c \ # or clang instead of cc
-framework Foundation -framework AppKit -Iinclude \
-O2 -Wall -Wextra -fno-exceptions -fPIC -shared -o libnfd.dylib
$ julia
julia> const libnfd = "./libnfd.dylib"
julia> function choose_file()
           path = Ref(Ptr{UInt8}())
           r = @ccall libnfd.NFD_OpenDialog(C_NULL::Ptr{Cchar}, C_NULL::Ptr{Cchar}, path::Ref{Ptr{UInt8}})::Cint
           if r == 2
               # User clicked "Cancel"
               out = nothing
           elseif r == 1
               out = unsafe_string(path[])
           else
               error()
           end
           return out
       end
julia> choose_file()

```

Edit: In Linux it works well in the `devel` branch.

---

<div class="post-metadata">

**Author:** ![Alex\_Tantos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex_tantos/32/10636_2.png) [@Alex\_Tantos](https://discourse.julialang.org/u/Alex_Tantos)\
**Post date:** [October 15, 2021, 8:50pm UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/39 "2021-10-15T20:50:27Z")

</div>

Just to let you know or any other interested in this, I ran your code above on my mac and when I reached the `const` assignment line got:

```julia
julia> const libnfd = "./libnfd.dylib"
ERROR: cannot assign a value to variable NativeFileDialog_jll.libnfd from module Main
Stacktrace:
 [1] top-level scope
   @ REPL[16]:1

```

---

<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:** [October 15, 2021, 8:58pm UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/40 "2021-10-15T20:58:34Z")

</div>

Scratch that. Just update your packages, you should get an [updated version](https://github.com/JuliaPackaging/Yggdrasil/pull/3755) of `NativeFileDialog_jll` which should be working better on macOS

---

<div class="post-metadata">

**Author:** ![Alex\_Tantos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex_tantos/32/10636_2.png) [@Alex\_Tantos](https://discourse.julialang.org/u/Alex_Tantos)\
**Post date:** [October 16, 2021, 8:02am UTC](https://discourse.julialang.org/t/file-choose-in-julia/69703/41 "2021-10-16T08:02:35Z")

</div>

Ok! The result is excellent! I report it here that it works perfectly for macos Catalina. No hang and no unexpected window behaviour.  
PS: Added `choose_file()` to `~/.julia/config/startup.jl` for now and waiting for the wrapper, I guess.

[Previous page](https://discourse.julialang.org/t/file-choose-in-julia/69703.md?page=1)

[Next page](https://discourse.julialang.org/t/file-choose-in-julia/69703.md?page=3)
