Splitting the PATH variable

I want to re-order path entries.

On unix, ENV["PATH"] = "/usr/local/bin:/usr/bin:/bin" or some such.
On windows, ENV["PATH"] = "c:\\usr\\local\\bin;c:\\usr\\bin;c:\\bin"
But it could be ENV["PATH"] = "c:\\usr\\local\\bin;c:\\usr\\bin;c:\\bin;\"c:\\usr\\directory name with; semicolon\\bin\"", so split(ENV["PATH"], Sys.iswindows() ? ";" : ":") isn’t perfect. Is there a better way?

PATH environment variables are not guaranteed to point to paths that exist in the system

OK, nevermind.

Why do you care? Most tools won’t work anyway if PATH includes directories with the list separator in their own path. Try for example this on Linux:

% mkdir -p /tmp/tmp:dir
% echo 'echo hello world' > /tmp/tmp:dir/helloworld
% chmod +x /tmp/tmp:dir/helloworld
% /tmp/tmp:dir/helloworld
hello world
% export PATH="/tmp/tmp:dir:${PATH}"
% helloworld                  
zsh: command not found: helloworld
1 Like

For the Windows case, an attempt at a splitpath() function:

# Julia 1.7:
function splitpath(epath::String)
    isw() = Sys.iswindows()
    ix = findall(occursin("\""), epath)
    if !isempty(ix)
        i0, p0 = 1, String[]
        for i in 1:2:length(ix)
            append!(p0, replace.(string.(split(epath[i0:ix[i]-1], isw() ? ";" : ":")), "\""=>""))
            push!(p0, replace.(string(epath[ix[i]:ix[i+1]-1]), "\"" => ""))
            i0 = ix[i+1]
        end
        if length(epath) > ix[end]
            append!(p0, replace.(string.(split(epath[ix[end]+1:end], isw() ? ";" : ":")), "\""=>""))
        end
    else
        p0 = string.(split(epath, isw() ? ";" : ":"))
    end
    filter!(!isempty,p0)
    return p0
end

# INPUT:
epath = "c:\\usr\\local\\bin;c:\\usr\\bin;c:\\bin;\"c:\\usr\\directory name with; semicolon\\bin\";c:;\"c:\\directory2 with; semicolon\""

# OUTPUT:
splitpath(epath)

6-element Vector{String}:
 "c:\\usr\\local\\bin"
 "c:\\usr\\bin"
 "c:\\bin"
 "c:\\usr\\directory name with; semicolon\\bin"
 "c:"
 "c:\\directory2 with; semicolon"
1 Like

Honestly, I was hoping there was a builtin akin to splitpath and joinpath that would do it. Given the complexity of @rafael.guerra’s answer, I may well stick with not supporting path entries with ;.

1 Like

Sorry but simplicity requires more time and skill :slight_smile: