# Check if is folder empty

**URL:** <https://discourse.julialang.org/t/check-if-is-folder-empty/122761>\
**Category:** Performance\
**Created:** [November 18, 2024, 10:31am UTC](https://discourse.julialang.org/t/check-if-is-folder-empty/122761 "2024-11-18T10:31:21Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![hhaensel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hhaensel/32/1207_2.png) [@hhaensel](https://discourse.julialang.org/u/hhaensel)\
**Post date:** [November 18, 2024, 10:31am UTC](https://discourse.julialang.org/t/check-if-is-folder-empty/122761/1 "2024-11-18T10:31:21Z")

</div>

What’s the best way to check if a folder is empty if folders possibly contains 10\_000 files?

```julia
isempty(readdir(mydir))

```

The point is that I want to list all empty subfolders of a directory, but mapping readdir on all non-empty folders before telling they’re not empty is not really performant in that case.

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [November 18, 2024, 12:39pm UTC](https://discourse.julialang.org/t/check-if-is-folder-empty/122761/2 "2024-11-18T12:39:56Z")

</div>

Maybe this works, not sure:

```julia
empty_dir(d) = stat(d).size <= stat(d).blksize && isempty(readdir(d; sort=false))

```

\_readdir is called, and you could simplify this to not loop:

```julia
julia> function _readdir2(dir::AbstractString; return_objects::Bool=false, join::Bool=false, sort::Bool=true)
           # Allocate space for uv_fs_t struct
           req = Libc.malloc(Base._sizeof_uv_fs)
           try
               # defined in sys.c, to call uv_fs_readdir, which sets errno on error.
               err = ccall(:uv_fs_scandir, Int32, (Ptr{Cvoid}, Ptr{Cvoid}, Cstring, Cint, Ptr{Cvoid}),
                           C_NULL, req, dir, 0, C_NULL)
               err < 0 && uv_error("readdir($(repr(dir)))", err)

               # iterate the listing into entries
               entries = return_objects ? DirEntry[] : String[]
               ent = Ref{Base.Filesystem.uv_dirent_t}()
               while Base.UV_EOF != ccall(:uv_fs_scandir_next, Cint, (Ptr{Cvoid}, Ptr{Base.Filesystem.uv_dirent_t}), req, ent)
                   name = unsafe_string(ent[].name)
                   if return_objects
                       rawtype = ent[].typ
                       push!(entries, DirEntry(dir, name, rawtype))
                   else
                       push!(entries, join ? joinpath(dir, name) : name)
                   end
               end

               # Clean up the request string
               Base.Filesystem.uv_fs_req_cleanup(req)

               # sort entries unless opted out
               sort && sort!(entries)

               return entries
           finally
               Libc.free(req)
           end
       end

```

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [November 18, 2024, 1:02pm UTC](https://discourse.julialang.org/t/check-if-is-folder-empty/122761/4 "2024-11-18T13:02:22Z")

</div>

There is a pending PR enabling lazy `readdir` operation:

> <https://github.com/JuliaLang/julia/pull/33478>
>
> The original libuv readdir one day became scandir, what is today the basis for J…ulia's \`readdir\`. The way that function works means all directory contents must be held in memory and sorted before processing. By utilizing the new readdir function in libuv we can instead process directory contents in a streaming fashion. This patch implements a \`lazyreaddir\` method to do this, delivering the directory contents trough a \`Channel\`.

---

<div class="post-metadata">

**Author:** ![hhaensel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hhaensel/32/1207_2.png) [@hhaensel](https://discourse.julialang.org/u/hhaensel)\
**Post date:** [November 18, 2024, 2:35pm UTC](https://discourse.julialang.org/t/check-if-is-folder-empty/122761/5 "2024-11-18T14:35:02Z")

</div>

That was really valuable feedback. Looking into the code I could come up with my own

```julia
function isemptydir(dir::AbstractString)
    # Allocate space for uv_fs_t struct
    req = Libc.malloc(Base.Filesystem._sizeof_uv_fs)
    ie = false
    try
        # defined in sys.c, to call uv_fs_readdir, which sets errno on error.
        err = ccall(:uv_fs_scandir, Int32, (Ptr{Cvoid}, Ptr{Cvoid}, Cstring, Cint, Ptr{Cvoid}),
                    C_NULL, req, dir, 0, C_NULL)
        err < 0 && Base.Filesystem.uv_error("readdir($(repr(dir)))", err)

        # iterate the listing into entries
        ent = Ref{Base.Filesystem.uv_dirent_t}()
        ie = Base.UV_EOF == ccall(:uv_fs_scandir_next, Cint, (Ptr{Cvoid}, Ptr{Base.Filesystem.uv_dirent_t}), req, ent)

        # Clean up the request string
        Base.Filesystem.uv_fs_req_cleanup(req)
    finally
        Libc.free(req)
    end
    return ie
end

```

and with this I see a significant but not large difference in memory consumption and performance on a mac-os:

```julia-repl
julia> @btime isemptydir("temp/hh")
  48.199 ms (0 allocations: 0 bytes)
false

julia> @btime isempty(readdir("temp/hh"))
  50.958 ms (110028 allocations: 5.18 MiB)
false

```
