1919 rename,
2020 readlink,
2121 readdir,
22+ readdirx,
2223 rm,
2324 samefile,
2425 sendfile,
2930 unlink,
3031 walkdir
3132
33+
3234# get and set current directory
3335
3436"""
@@ -929,7 +931,78 @@ julia> readdir(abspath("base"), join=true)
929931 "/home/JuliaUser/dev/julia/base/weakkeydict.jl"
930932```
931933"""
932- function readdir (dir:: AbstractString ; join:: Bool = false , sort:: Bool = true )
934+ readdir (; join:: Bool = false , kwargs... ) = readdir (join ? pwd () : " ." ; join, kwargs... ):: Vector{String}
935+ readdir (dir:: AbstractString ; kwargs... ) = _readdir (dir; return_objects= false , kwargs... ):: Vector{String}
936+
937+ # this might be better as an Enum but they're not available here
938+ # UV_DIRENT_T
939+ const UV_DIRENT_UNKNOWN = Cint (0 )
940+ const UV_DIRENT_FILE = Cint (1 )
941+ const UV_DIRENT_DIR = Cint (2 )
942+ const UV_DIRENT_LINK = Cint (3 )
943+ const UV_DIRENT_FIFO = Cint (4 )
944+ const UV_DIRENT_SOCKET = Cint (5 )
945+ const UV_DIRENT_CHAR = Cint (6 )
946+ const UV_DIRENT_BLOCK = Cint (7 )
947+
948+ """
949+ DirEntry
950+
951+ A type representing a filesystem entry that contains the name of the entry, the directory, and
952+ the raw type of the entry. The full path of the entry can be obtained lazily by accessing the
953+ `path` field. The type of the entry can be checked for by calling [`isfile`](@ref), [`isdir`](@ref),
954+ [`islink`](@ref), [`isfifo`](@ref), [`issocket`](@ref), [`ischardev`](@ref), and [`isblockdev`](@ref)
955+ """
956+ struct DirEntry
957+ dir:: String
958+ name:: String
959+ rawtype:: Cint
960+ end
961+ function Base. getproperty (obj:: DirEntry , p:: Symbol )
962+ if p === :path
963+ return joinpath (obj. dir, obj. name)
964+ else
965+ return getfield (obj, p)
966+ end
967+ end
968+ Base. propertynames (:: DirEntry ) = (:dir , :name , :path , :rawtype )
969+ Base. isless (a:: DirEntry , b:: DirEntry ) = a. dir == b. dir ? isless (a. name, b. name) : isless (a. dir, b. dir)
970+ Base. hash (o:: DirEntry , h:: UInt ) = hash (o. dir, hash (o. name, hash (o. rawtype, h)))
971+ Base.:(== )(a:: DirEntry , b:: DirEntry ) = a. name == b. name && a. dir == b. dir && a. rawtype == b. rawtype
972+ joinpath (obj:: DirEntry , args... ) = joinpath (obj. path, args... )
973+ isunknown (obj:: DirEntry ) = obj. rawtype == UV_DIRENT_UNKNOWN
974+ islink (obj:: DirEntry ) = isunknown (obj) ? islink (obj. path) : obj. rawtype == UV_DIRENT_LINK
975+ isfile (obj:: DirEntry ) = (isunknown (obj) || islink (obj)) ? isfile (obj. path) : obj. rawtype == UV_DIRENT_FILE
976+ isdir (obj:: DirEntry ) = (isunknown (obj) || islink (obj)) ? isdir (obj. path) : obj. rawtype == UV_DIRENT_DIR
977+ isfifo (obj:: DirEntry ) = (isunknown (obj) || islink (obj)) ? isfifo (obj. path) : obj. rawtype == UV_DIRENT_FIFO
978+ issocket (obj:: DirEntry ) = (isunknown (obj) || islink (obj)) ? issocket (obj. path) : obj. rawtype == UV_DIRENT_SOCKET
979+ ischardev (obj:: DirEntry ) = (isunknown (obj) || islink (obj)) ? ischardev (obj. path) : obj. rawtype == UV_DIRENT_CHAR
980+ isblockdev (obj:: DirEntry ) = (isunknown (obj) || islink (obj)) ? isblockdev (obj. path) : obj. rawtype == UV_DIRENT_BLOCK
981+
982+ """
983+ readdirx(dir::AbstractString=pwd(); sort::Bool = true) -> Vector{DirEntry}
984+
985+ Return a vector of [`DirEntry`](@ref) objects representing the contents of the directory `dir`,
986+ or the current working directory if not given. If `sort` is true, the returned vector is
987+ sorted by name.
988+
989+ Unlike [`readdir`](@ref), `readdirx` returns [`DirEntry`](@ref) objects, which contain the name of the
990+ file, the directory it is in, and the type of the file which is determined during the
991+ directory scan. This means that calls to [`isfile`](@ref), [`isdir`](@ref), [`islink`](@ref), [`isfifo`](@ref),
992+ [`issocket`](@ref), [`ischardev`](@ref), and [`isblockdev`](@ref) can be made on the
993+ returned objects without further stat calls. However, for some filesystems, the type of the file
994+ cannot be determined without a stat call. In these cases the `rawtype` field of the [`DirEntry`](@ref))
995+ object will be 0 (`UV_DIRENT_UNKNOWN`) and [`isfile`](@ref) etc. will fall back to a `stat` call.
996+
997+ ```julia
998+ for obj in readdirx()
999+ isfile(obj) && println("$(obj. name) is a file with path $(obj. path) ")
1000+ end
1001+ ```
1002+ """
1003+ readdirx (dir:: AbstractString = pwd (); sort:: Bool = true ) = _readdir (dir; return_objects= true , sort):: Vector{DirEntry}
1004+
1005+ function _readdir (dir:: AbstractString ; return_objects:: Bool = false , join:: Bool = false , sort:: Bool = true )
9331006 # Allocate space for uv_fs_t struct
9341007 req = Libc. malloc (_sizeof_uv_fs)
9351008 try
@@ -939,11 +1012,16 @@ function readdir(dir::AbstractString; join::Bool=false, sort::Bool=true)
9391012 err < 0 && uv_error (" readdir($(repr (dir)) )" , err)
9401013
9411014 # iterate the listing into entries
942- entries = String[]
1015+ entries = return_objects ? DirEntry[] : String[]
9431016 ent = Ref {uv_dirent_t} ()
9441017 while Base. UV_EOF != ccall (:uv_fs_scandir_next , Cint, (Ptr{Cvoid}, Ptr{uv_dirent_t}), req, ent)
9451018 name = unsafe_string (ent[]. name)
946- push! (entries, join ? joinpath (dir, name) : name)
1019+ if return_objects
1020+ rawtype = ent[]. typ
1021+ push! (entries, DirEntry (dir, name, rawtype))
1022+ else
1023+ push! (entries, join ? joinpath (dir, name) : name)
1024+ end
9471025 end
9481026
9491027 # Clean up the request string
@@ -957,8 +1035,6 @@ function readdir(dir::AbstractString; join::Bool=false, sort::Bool=true)
9571035 Libc. free (req)
9581036 end
9591037end
960- readdir (; join:: Bool = false , sort:: Bool = true ) =
961- readdir (join ? pwd () : " ." , join= join, sort= sort)
9621038
9631039"""
9641040 walkdir(dir; topdown=true, follow_symlinks=false, onerror=throw)
0 commit comments