Skip to content

Commit

Permalink
Add splitpath(p::AbstractString) to Base.Filesystem. (#28156)
Browse files Browse the repository at this point in the history
  • Loading branch information
NHDaly authored and StefanKarpinski committed Sep 24, 2018
1 parent 99e0b3b commit abd9072
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 1 deletion.
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,7 @@ export
splitdir,
splitdrive,
splitext,
splitpath,

# filesystem operations
cd,
Expand Down
44 changes: 43 additions & 1 deletion base/path.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ export
relpath,
splitdir,
splitdrive,
splitext
splitext,
splitpath

if Sys.isunix()
const path_separator = "/"
Expand Down Expand Up @@ -129,6 +130,12 @@ julia> splitdir("/home/myuser")
"""
function splitdir(path::String)
a, b = splitdrive(path)
_splitdir_nodrive(a,b)
end

# Common splitdir functionality without splitdrive, needed for splitpath.
_splitdir_nodrive(path::String) = _splitdir_nodrive("", path)
function _splitdir_nodrive(a::String, b::String)
m = match(path_dir_splitter,b)
m === nothing && return (a,b)
a = string(a, isempty(m.captures[1]) ? m.captures[2][1] : m.captures[1])
Expand Down Expand Up @@ -196,6 +203,41 @@ function pathsep(paths::AbstractString...)
return path_separator
end

"""
splitpath(path::AbstractString) -> Vector{String}
Split a file path into all its path components. This is the opposite of
`joinpath`. Returns an array of substrings, one for each directory or file in
the path, including the root directory if present.
# Examples
```jldoctest
julia> splitpath("/home/myuser/example.jl")
4-element Array{String,1}:
"/"
"home"
"myuser"
"example.jl"
```
"""
function splitpath(p::String)
drive, p = splitdrive(p)
out = String[]
isempty(p) && (pushfirst!(out,p)) # "" means the current directory.
while !isempty(p)
dir, base = _splitdir_nodrive(p)
dir == p && (pushfirst!(out, dir); break) # Reached root node.
if !isempty(base) # Skip trailing '/' in basename
pushfirst!(out, base)
end
p = dir
end
if !isempty(drive) # Tack the drive back on to the first element.
out[1] = drive*out[1] # Note that length(out) is always >= 1.
end
return out
end

joinpath(a::AbstractString) = a

"""
Expand Down
1 change: 1 addition & 0 deletions doc/src/base/file.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,5 @@ Base.Filesystem.expanduser
Base.Filesystem.splitdir
Base.Filesystem.splitdrive
Base.Filesystem.splitext
Base.Filesystem.splitpath
```
36 changes: 36 additions & 0 deletions test/path.jl
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,42 @@
end
@test relpath(S(joinpath("foo","bar")), S("foo")) == "bar"

@testset "splitpath" begin
@test splitpath(joinpath("a","b","c")) == ["a", "b", "c"]
@test splitpath("") == [""]

@test splitpath(joinpath("cats are", "gr8t")) == ["cats are", "gr8t"]
@test splitpath(joinpath(" ", " ")) == [" ", " "]

# Unix-style paths are understood by all systems.
@test splitpath("/a/b") == ["/", "a", "b"]
@test splitpath("/") == ["/"]
@test splitpath("a/") == ["a"]
@test splitpath("a/b/") == ["a", "b"]
@test splitpath("a.dir/b.txt") == ["a.dir", "b.txt"]
@test splitpath("///") == ["/"]
@test splitpath("///a///b///") == ["/", "a", "b"]

if Sys.iswindows()
@test splitpath("C:\\\\a\\b\\c") == ["C:\\", "a", "b", "c"]
@test splitpath("C:\\\\") == ["C:\\"]
@test splitpath("J:\\") == ["J:\\"]
@test splitpath("C:") == ["C:"]
@test splitpath("C:a") == ["C:a"]
@test splitpath("C:a\\b") == ["C:a", "b"]

@test splitpath("a\\") == ["a"]
@test splitpath("a\\\\b\\\\") == ["a","b"]
@test splitpath("a.dir\\b.txt") == ["a.dir", "b.txt"]
@test splitpath("\\a\\b\\") == ["\\", "a","b"]
@test splitpath("\\\\a\\b") == ["\\\\a\\b"] # This is actually a valid drive name in windows.

@test splitpath("/a/b\\c/d\\\\e") == ["/", "a", "b", "c", "d", "e"]
@test splitpath("/\\/\\") == ["/"]
@test splitpath("\\/\\a/\\//b") == ["\\","a","b"]
end
end

@testset "splitting" begin
@test joinpath(splitdir(S(homedir()))...) == homedir()
@test string(splitdrive(S(homedir()))...) == homedir()
Expand Down

0 comments on commit abd9072

Please sign in to comment.