diff --git a/base/shell.jl b/base/shell.jl index e94ec466e2c05b..a5b25fc63ea44d 100644 --- a/base/shell.jl +++ b/base/shell.jl @@ -288,11 +288,11 @@ This function may be useful in concert with the `windows_verbatim` flag to ```julia wincmd(c::String) = - run(Cmd(Cmd(["cmd.exe", "/s /c \" \$c \""]); + run(Cmd(Cmd(["cmd.exe", "/s /c \\" \$c \\""]); windows_verbatim=true)) wincmd_echo(s::String) = wincmd("echo " * Base.shell_escape_wincmd(s)) -wincmd_echo("hello \$(ENV["USERNAME"]) & the \"whole\" world! (=^I^=)") +wincmd_echo("hello \$(ENV["USERNAME"]) & the \\"whole\\" world! (=^I^=)") ``` But take note that if the input string `s` contains a `%`, the argument list @@ -319,7 +319,7 @@ run(setenv(`cmd /C echo %cmdargs%`, "cmdargs" => cmdargs)) ```julia to_print = "All for 1 & 1 for all!" to_print_esc = Base.shell_escape_wincmd(Base.shell_escape_wincmd(to_print)) - run(Cmd(Cmd(["cmd", "/S /C \" break | echo \$(to_print_esc) \""]), windows_verbatim=true)) + run(Cmd(Cmd(["cmd", "/S /C \\" break | echo \$(to_print_esc) \\""]), windows_verbatim=true)) ``` With an I/O stream parameter `io`, the result will be written there, diff --git a/test/read.jl b/test/read.jl index aa897342393a10..78ecded83c80a3 100644 --- a/test/read.jl +++ b/test/read.jl @@ -98,30 +98,27 @@ s = io(text) close(s) push!(l, ("PipeEndpoint", io)) -#FIXME See https://github.com/JuliaLang/julia/issues/14747 -# Reading from open(::Command) seems to deadlock on Linux -#= -if !Sys.iswindows() -# Windows type command not working? -# See "could not spawn `type 'C:\Users\appveyor\AppData\Local\Temp\1\jul3516.tmp\file.txt'`" -#https://ci.appveyor.com/project/StefanKarpinski/julia/build/1.0.12733/job/hpwjs4hmf03vs5ag#L1244 - -# Pipe +# Pipe (#14747) io = (text) -> begin write(filename, text) - open(`$(Sys.iswindows() ? "type" : "cat") $filename`)[1] -# Was open(`echo -n $text`)[1] -# See https://github.com/JuliaLang/julia/issues/14747 + # we can skip using shell_escape_wincmd, since ", ^, and % aren't legal in + # a filename, so unconditionally wrapping in " is sufficient (okay, that's + # a lie, since ^ and % actually are legal, but DOS is broken) + if Sys.iswindows() + cmd = Cmd(["cmd.exe", "/c type \"$(replace(filename, '/' => '\\'))\""]) + cmd = Cmd(cmd; windows_verbatim=true) + cmd = pipeline(cmd, stderr=devnull) + else + cmd = `cat $filename` + end + open(cmd) end s = io(text) @test isa(s, IO) -@test isa(s, Pipe) +@test isa(s, Base.Process) close(s) -push!(l, ("Pipe", io)) - -end -=# +push!(l, ("Process", io)) open_streams = [] @@ -140,7 +137,6 @@ end verbose = false for (name, f) in l - local f local function io(text=text) local s = f(text) push!(open_streams, s) @@ -319,9 +315,9 @@ for (name, f) in l text = old_text write(filename, text) - if !(typeof(io()) in [Base.PipeEndpoint, Pipe, TCPSocket]) + if !isa(io(), Union{Base.PipeEndpoint, Base.AbstractPipe, TCPSocket}) verbose && println("$name position...") - @test (s = io(); read!(s, Vector{UInt8}(undef, 4)); position(s)) == 4 + @test (s = io(); read!(s, Vector{UInt8}(undef, 4)); position(s)) == 4 verbose && println("$name seek...") for n = 0:length(text)-1