Run Command without Single Quote

Windows:
I want Julia to run a command to 7-zip a file, i.e. following works in my terminal:

7z a c:\test\f1.zip c:\test\f1.txt

I have to use Double Quote or No Quote for the file name, otherwise, If I use Single Quote, 7 zip Output an Error

However, when I do this in Julia,

cc = `7z a c:\\test\\f1.zip c:\\test\\f1.txt`

run(cc)

This failed, because when I do
println(cc)

It generate this output:

7z a 'c:\test\f1.zip' 'c:\test\f1.txt'

How come Julia added single quote around file name? I dont like it because it will break my 7-zip command. 7z only accept double quote or No quote.

Thank you

Have you tried it without the double quotes and using backslashes to escape the spaces?

I changed my example, it still does not work…

I’m pretty sure that’s just a printing thing (the single quotes). That command works fine for me:

julia> cmd = `7z a E:\\Downloads\\foo.zip E:\\Downloads\\foo`
`7z a 'E:\Downloads\foo.zip' 'E:\Downloads\foo'`

julia> run(cmd)

7-Zip [64] 16.04 : Copyright (c) 1999-2016 Igor Pavlov : 2016-10-04

Open archive: E:\Downloads\foo.zip
--
Path = E:\Downloads\foo.zip
Type = zip
Physical Size = 2412099
Comment = e16eaa0b8d8ccf3f432c9ef46cbbc6453789fce7

Scanning the drive:
1 folder, 0 files, 0 bytes

Updating archive: E:\Downloads\foo.zip

Items to compress: 1


Files read from disk: 0
Archive size: 2412099 bytes (2356 KiB)
Everything is Ok
Process(`7z a 'E:\Downloads\foo.zip' 'E:\Downloads\foo'`, ProcessExited(0))

I am using Windows 10 Enterprise + Julia 1.1 + 7-zip (2019-02-21) 64 bits

cc = `7z a c:\\temp\\f1.zip c:\\temp\\f1.txt`
run(cc)

IOError: could not spawn 7z a 'c:\temp\f1.zip' 'c:\temp\f1.txt': no such file or directory (ENOENT)
_spawn_primitive(::String, ::Cmd, ::Array{Any,1}) at process.jl:400
setup_stdios(::getfield(Base, Symbol(“##505#506”)){Cmd}, ::Array{Any,1}) at process.jl:413
_spawn at process.jl:412 [inlined]
run#515(::Bool, ::Function, ::Cmd) at process.jl:725
run(::Cmd) at process.jl:724
top-level scope at none:0

Then I open a windows terminal
Without Single Quote, it works:
7z_1

Adding Single Quote, it failed, exactly the same as Julia 's case

@pfitzseb Could you try this:

  1. In a windows command line, you try to add Single Quote to your file name, does it still work?
    i.e. you will run this in windows command line, not Julia REPL:

7z a 'E:\\Downloads\\foo.zip' 'E:\\Downloads\\foo'

  1. If you upgrade you 7 zip to v19 or latest 2019-02 version, with 64-bit, does it still work?

Thank you

Those are different errors. I’m pretty sure Julia can’t find 7z for some reason, so try specifying the complete path (e.g. as joinpath(Sys.BINDIR, "7z") if you want to use the 7zip shipped with Julia).

Isn’t the latest problem that you have c: instead of C:?

I am also running into this issue

In the simple example below, the command fails.

If I past the command string (line 2 of the code snippet) - without the backticks and WITHOUT the single apostrophes of the first argument - into a cmd.exe window; things work perfectly

julia>     cmd = Cmd(`rename $(fi) $(fnonlyNew)`,windows_verbatim=true)
`rename 'C:\temp\abc.jpg' 2020-10-06T132158_abc.jpg`

julia>     run(cmd)
ERROR: IOError: could not spawn `rename 'C:\temp\abc.jpg' 2020-10-06T132158_abc.jpg`: no such file or directory (ENOENT)
Stacktrace:
 [1] _spawn_primitive(::String, ::Cmd, ::Array{Any,1}) at .\process.jl:99
 [2] #585 at .\process.jl:112 [inlined]
 [3] setup_stdios(::Base.var"#585#586"{Cmd}, ::Array{Any,1}) at .\process.jl:196
 [4] _spawn at .\process.jl:111 [inlined]
 [5] run(::Cmd; wait::Bool) at .\process.jl:439
 [6] run(::Cmd) at .\process.jl:438
 [7] top-level scope at REPL[113]:1
 [8] include_string(::Function, ::Module, ::String, ::String) at .\loading.jl:1088

for what it’s worth. For my use case, powershell does the trick. This works:

cmd = `powershell.exe Rename-Item -Path $(fi) -NewName $(fnonlyNew)`
run(cmd)

rename isn’t a program on Windows, it’s a cmd built-in afaict. Consequently, you need to run cmd it inside of cmd:

julia> run(Cmd(`cmd /c rename $("test.jl") $("test2.jl")`, windows_verbatim=true))
Process(`cmd /c rename test.jl test2.jl`, ProcessExited(0))

The windows_verbatim stuff is unnecessary as well:

julia> run(`cmd /c rename $("test.jl") $("test2.jl")`)
Process(`cmd /c rename test.jl test2.jl`, ProcessExited(0))
2 Likes

I am facing this problem as well. I want to run

polyquad find -s tri -q 2 -n 1 -p -V > output.txt

This works fine in the terminal. However, if I try to do it via

run(`polyquad find -s tri -q 2 -n 1 -p -V > output.txt`)

then I get the error

special characters "#{}()[]<>|&*?~;" must be quoted in commands

If I try

run(`polyquad find -s tri -q 2 -n 1 -p -V '>' output.txt`)

then the program polyquad does not like the quotes.

Is there any way to execute an instruction in Julia exactly as it is written, without any quotes?

Julia isn’t running a shell, so things like > won’t work out of the box. You can either use pipeline to redirect stdout/in/err or just run your whole command in a shell with e.g.

run(`/bin/bash -e 'polyquad find -s tri -q 2 -n 1 -p -V > output.txt'`)

or something like that.

2 Likes

Thanks @pfitzseb. If output.txt is not the name of the file, but it is stored in a string OutputFile, how can I proceed? Because

run(`/bin/bash -e 'polyquad find -s tri -q 2 -n 1 -p -V > $(OutputFile)'`)

is interpreted as the command

polyquad find -s tri -q 2 -n 1 -p -V > $(OutputFile)

and does not work.

As noted by @pfitzseb above, pipeline should work here:

output_file = "output.txt"
run(pipeline(`polyquad find -s tri -q 2 -n 1 -p -V`, output_file))
1 Like

Yes, it works. Thank you :slight_smile: