@@ -913,7 +913,79 @@ julia> readdir(abspath("base"), join=true)
913
913
"/home/JuliaUser/dev/julia/base/weakkeydict.jl"
914
914
```
915
915
"""
916
- function readdir (dir:: AbstractString ; join:: Bool = false , sort:: Bool = true )
916
+ readdir (; join:: Bool = false , kwargs... ) = readdir (join ? pwd () : " ." ; join, kwargs... ):: Vector{String}
917
+ readdir (dir:: AbstractString ; kwargs... ) = _readdir (dir; return_objects= false , kwargs... ):: Vector{String}
918
+
919
+ # this might be better as an Enum but they're not available here
920
+ # UV_DIRENT_T
921
+ const UV_DIRENT_UNKNOWN = Cint (0 )
922
+ const UV_DIRENT_FILE = Cint (1 )
923
+ const UV_DIRENT_DIR = Cint (2 )
924
+ const UV_DIRENT_LINK = Cint (3 )
925
+ const UV_DIRENT_FIFO = Cint (4 )
926
+ const UV_DIRENT_SOCKET = Cint (5 )
927
+ const UV_DIRENT_CHAR = Cint (6 )
928
+ const UV_DIRENT_BLOCK = Cint (7 )
929
+
930
+ """
931
+ DirEntry
932
+
933
+ A type representing a filesystem entry that contains the name of the entry, the directory, and
934
+ the raw type of the entry. The full path of the entry can be obtained lazily by accessing the
935
+ `path` field. The type of the entry can be checked for by calling [`isfile`](@ref), [`isdir`](@ref),
936
+ [`islink`](@ref), [`isfifo`](@ref), [`issocket`](@ref), [`ischardev`](@ref), and [`isblockdev`](@ref)
937
+ """
938
+ struct DirEntry
939
+ dir:: String
940
+ name:: String
941
+ rawtype:: Cint
942
+ end
943
+ function Base. getproperty (obj:: DirEntry , p:: Symbol )
944
+ if p === :path
945
+ return joinpath (obj. dir, obj. name)
946
+ else
947
+ return getfield (obj, p)
948
+ end
949
+ end
950
+ Base. propertynames (:: DirEntry ) = (:dir , :name , :path , :rawtype )
951
+ Base. isless (a:: DirEntry , b:: DirEntry ) = a. dir == b. dir ? isless (a. name, b. name) : isless (a. dir, b. dir)
952
+ Base. hash (o:: DirEntry , h:: UInt ) = hash (o. dir, hash (o. name, hash (o. rawtype, h)))
953
+ Base.:(== )(a:: DirEntry , b:: DirEntry ) = a. name == b. name && a. dir == b. dir && a. rawtype == b. rawtype
954
+ joinpath (obj:: DirEntry , args... ) = joinpath (obj. path, args... )
955
+ isunknown (obj:: DirEntry ) = obj. rawtype == UV_DIRENT_UNKNOWN
956
+ islink (obj:: DirEntry ) = isunknown (obj) ? islink (obj. path) : obj. rawtype == UV_DIRENT_LINK
957
+ isfile (obj:: DirEntry ) = (isunknown (obj) || islink (obj)) ? isfile (obj. path) : obj. rawtype == UV_DIRENT_FILE
958
+ isdir (obj:: DirEntry ) = (isunknown (obj) || islink (obj)) ? isdir (obj. path) : obj. rawtype == UV_DIRENT_DIR
959
+ isfifo (obj:: DirEntry ) = (isunknown (obj) || islink (obj)) ? isfifo (obj. path) : obj. rawtype == UV_DIRENT_FIFO
960
+ issocket (obj:: DirEntry ) = (isunknown (obj) || islink (obj)) ? issocket (obj. path) : obj. rawtype == UV_DIRENT_SOCKET
961
+ ischardev (obj:: DirEntry ) = (isunknown (obj) || islink (obj)) ? ischardev (obj. path) : obj. rawtype == UV_DIRENT_CHAR
962
+ isblockdev (obj:: DirEntry ) = (isunknown (obj) || islink (obj)) ? isblockdev (obj. path) : obj. rawtype == UV_DIRENT_BLOCK
963
+ realpath (obj:: DirEntry ) = realpath (obj. path)
964
+
965
+ """
966
+ _readdirx(dir::AbstractString=pwd(); sort::Bool = true) -> Vector{DirEntry}
967
+
968
+ Return a vector of [`DirEntry`](@ref) objects representing the contents of the directory `dir`,
969
+ or the current working directory if not given. If `sort` is true, the returned vector is
970
+ sorted by name.
971
+
972
+ Unlike [`readdir`](@ref), `_readdirx` returns [`DirEntry`](@ref) objects, which contain the name of the
973
+ file, the directory it is in, and the type of the file which is determined during the
974
+ directory scan. This means that calls to [`isfile`](@ref), [`isdir`](@ref), [`islink`](@ref), [`isfifo`](@ref),
975
+ [`issocket`](@ref), [`ischardev`](@ref), and [`isblockdev`](@ref) can be made on the
976
+ returned objects without further stat calls. However, for some filesystems, the type of the file
977
+ cannot be determined without a stat call. In these cases the `rawtype` field of the [`DirEntry`](@ref))
978
+ object will be 0 (`UV_DIRENT_UNKNOWN`) and [`isfile`](@ref) etc. will fall back to a `stat` call.
979
+
980
+ ```julia
981
+ for obj in _readdirx()
982
+ isfile(obj) && println("\$ (obj.name) is a file with path \$ (obj.path)")
983
+ end
984
+ ```
985
+ """
986
+ _readdirx (dir:: AbstractString = pwd (); sort:: Bool = true ) = _readdir (dir; return_objects= true , sort):: Vector{DirEntry}
987
+
988
+ function _readdir (dir:: AbstractString ; return_objects:: Bool = false , join:: Bool = false , sort:: Bool = true )
917
989
# Allocate space for uv_fs_t struct
918
990
req = Libc. malloc (_sizeof_uv_fs)
919
991
try
@@ -923,11 +995,16 @@ function readdir(dir::AbstractString; join::Bool=false, sort::Bool=true)
923
995
err < 0 && uv_error (" readdir($(repr (dir)) )" , err)
924
996
925
997
# iterate the listing into entries
926
- entries = String[]
998
+ entries = return_objects ? DirEntry[] : String[]
927
999
ent = Ref {uv_dirent_t} ()
928
1000
while Base. UV_EOF != ccall (:uv_fs_scandir_next , Cint, (Ptr{Cvoid}, Ptr{uv_dirent_t}), req, ent)
929
1001
name = unsafe_string (ent[]. name)
930
- push! (entries, join ? joinpath (dir, name) : name)
1002
+ if return_objects
1003
+ rawtype = ent[]. typ
1004
+ push! (entries, DirEntry (dir, name, rawtype))
1005
+ else
1006
+ push! (entries, join ? joinpath (dir, name) : name)
1007
+ end
931
1008
end
932
1009
933
1010
# Clean up the request string
@@ -941,8 +1018,6 @@ function readdir(dir::AbstractString; join::Bool=false, sort::Bool=true)
941
1018
Libc. free (req)
942
1019
end
943
1020
end
944
- readdir (; join:: Bool = false , sort:: Bool = true ) =
945
- readdir (join ? pwd () : " ." , join= join, sort= sort)
946
1021
947
1022
"""
948
1023
walkdir(dir; topdown=true, follow_symlinks=false, onerror=throw)
0 commit comments