From 1ec9ab429b54ee09d3c9f0cf6d857f12fd72d1f0 Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Thu, 29 Aug 2019 12:21:29 -0400 Subject: [PATCH] readdir: add `join` option to join `dir` with names --- NEWS.md | 1 + base/file.jl | 69 +++++++++++++++++++++++++++++++++++++++++++--------- test/file.jl | 28 +++++++++++++++++++++ 3 files changed, 86 insertions(+), 12 deletions(-) diff --git a/NEWS.md b/NEWS.md index 321b61246f9fd..2ff018ce96ce4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -24,6 +24,7 @@ New library functions * The `splitpath` function now accepts any `AbstractString` whereas previously it only accepted paths of type `String` ([#33012]). * The `tempname` function now takes an optional `parent::AbstractString` argument to give it a directory in which to attempt to produce a temporary path name ([#33090]). * The `tempname` function now takes a `cleanup::Bool` keyword argument defaulting to `true`, which causes the process to try to ensure that any file or directory at the path returned by `tempname` is deleted upon process exit ([#33090]). +* The `readdir` function now takes a `join::Bool` keyword argument defaulting to `false`, which when set causes `readdir` to join its directory argument with each listed name ([#33113]). Standard library changes diff --git a/base/file.jl b/base/file.jl index ec07dddd221be..b1dcee009d5e3 100644 --- a/base/file.jl +++ b/base/file.jl @@ -671,27 +671,73 @@ struct uv_dirent_t end """ - readdir(dir::AbstractString=".") -> Vector{String} + readdir(dir::AbstractString=pwd(); join::Bool=true) -> Vector{String} -Return the files and directories in the directory `dir` (or the current working directory if not given). +Return the names in the directory `dir` or the current working directory if not +given. When `join` is false, `readdir` returns just the names in the directory +as is; when `join` is true, it returns `joinpath(dir, name)` for each `name` so +that the returned strings are full paths. If you want to get absolute paths +back, call `readdir` with an absolute directory path and `join` set to true. + +!!! compat "Julia 1.4" + The `join` keyword argument requires at least Julia 1.4. # Examples ```julia-repl -julia> readdir("/home/JuliaUser/Projects/julia") -34-element Array{String,1}: - ".circleci" - ".freebsdci.sh" +julia> cd("/home/JuliaUser/dev/julia") + +julia> readdir() +30-element Array{String,1}: + ".appveyor.yml" ".git" ".gitattributes" - ".github" ⋮ - "test" "ui" "usr" "usr-staging" + +julia> readdir(join=true) +30-element Array{String,1}: + "/home/JuliaUser/dev/julia/.appveyor.yml" + "/home/JuliaUser/dev/julia/.git" + "/home/JuliaUser/dev/julia/.gitattributes" + ⋮ + "/home/JuliaUser/dev/julia/ui" + "/home/JuliaUser/dev/julia/usr" + "/home/JuliaUser/dev/julia/usr-staging" + +julia> readdir("base") +145-element Array{String,1}: + ".gitignore" + "Base.jl" + "Enums.jl" + ⋮ + "version_git.sh" + "views.jl" + "weakkeydict.jl" + +julia> readdir("base", join=true) +145-element Array{String,1}: + "base/.gitignore" + "base/Base.jl" + "base/Enums.jl" + ⋮ + "base/version_git.sh" + "base/views.jl" + "base/weakkeydict.jl"``` + +julia> readdir(abspath("base"), join=true) +145-element Array{String,1}: + "/home/JuliaUser/dev/julia/base/.gitignore" + "/home/JuliaUser/dev/julia/base/Base.jl" + "/home/JuliaUser/dev/julia/base/Enums.jl" + ⋮ + "/home/JuliaUser/dev/julia/base/version_git.sh" + "/home/JuliaUser/dev/julia/base/views.jl" + "/home/JuliaUser/dev/julia/base/weakkeydict.jl" ``` """ -function readdir(dir::AbstractString) +function readdir(dir::AbstractString=pwd(); join::Bool=false) # Allocate space for uv_fs_t struct uv_readdir_req = zeros(UInt8, ccall(:jl_sizeof_uv_fs_t, Int32, ())) @@ -704,7 +750,8 @@ function readdir(dir::AbstractString) entries = String[] ent = Ref{uv_dirent_t}() while Base.UV_EOF != ccall(:uv_fs_scandir_next, Cint, (Ptr{Cvoid}, Ptr{uv_dirent_t}), uv_readdir_req, ent) - push!(entries, unsafe_string(ent[].name)) + name = unsafe_string(ent[].name) + push!(entries, join ? joinpath(dir, name) : name) end # Clean up the request string @@ -713,8 +760,6 @@ function readdir(dir::AbstractString) return entries end -readdir() = readdir(".") - """ walkdir(dir; topdown=true, follow_symlinks=false, onerror=throw) diff --git a/test/file.jl b/test/file.jl index fe93448adabbe..d4e042adf0842 100644 --- a/test/file.jl +++ b/test/file.jl @@ -1404,3 +1404,31 @@ end @test sizeof(basename(tmpdir)) == 6 end end + +@testset "readir tests" begin + ≛(a, b) = sort(a) == sort(b) + mktempdir() do dir + d = cd(pwd, dir) # might resolve symlinks + @test isempty(readdir(d)) + @test isempty(readdir(d, join=true)) + cd(d) do + @test isempty(readdir()) + @test isempty(readdir(join=true)) + end + touch(joinpath(d, "file")) + mkdir(joinpath(d, "dir")) + names = ["dir", "file"] + paths = [joinpath(d, x) for x in names] + @test readdir(d) ≛ names + @test readdir(d, join=true) ≛ paths + cd(d) do + @test readdir() ≛ names + @test readdir(join=true) ≛ paths + end + t, b = splitdir(d) + cd(t) do + @test readdir(b) ≛ names + @test readdir(b, join=true) ≛ [joinpath(b, x) for x in names] + end + end +end