1

How do I use exec.command to start a file with spaces? Adding quotes doesn't seem to work, neither does " or %20 instead of the spaces.

package main

import (
"fmt"
"os/exec"
)

func main() {
    StartProcess("C:\\File With Spaces.txt")
}

func StartProcess(Filename string) {
    Filename = "\"" + Filename + "\""
    cmd := exec.Command("cmd","/C start",Filename)
    err := cmd.Start()
    if err!=nil{
    fmt.Println(err)
    }
}
Gordon Truslove
  • 724
  • 2
  • 10
  • 19
  • Do not put " inside filename (unless your filename really has " in it). "\"a.txt\"" will try to open "a.txt", not a.txt. Is that what you want? Also, you can use back quotes (http://golang.org/ref/spec#String_literals) if you have too many characters that need escaping. For example, this `c:\a\b\c\d.txt` just works as is. – alex Sep 03 '14 at 00:32
  • The problem is, I can't open c:\a b.txt – Gordon Truslove Sep 03 '14 at 08:28

3 Answers3

1

you need to cmd.Wait and check for any errors returned by your methods

package main

import (
    "bytes"
    "log"
    "os"
    "os/exec"
)

func main() {
    args := os.Args

    cmd := exec.Command(args[1], args[2:]...)
    var b bytes.Buffer
    cmd.Stdout = &b

    err := cmd.Start()
    if err != nil {
        log.Fatal(err)
    }
    if err := cmd.Wait(); err != nil {
        log.Fatal(err)
    }

    if _, err := os.Stdout.Write(b.Bytes()); err != nil {
        log.Fatal(err)
    }
}
fabrizioM
  • 46,639
  • 15
  • 102
  • 119
1

If you're trying to run an executable on Windows then you don't need command prompt. You just need to pass in the executable path to the shell and it will fire.

E.g:

func StartProcess(Filename string) {
    // Filename = "cmd /C start \"" + Filename + "\"" 
    cmd := exec.Command(Filename)
    err := cmd.Start()
    if err!=nil{
    fmt.Println(err)
    }
}

StartProcess("C:\\path to executable\\executable.exe")

That said, generally with all frameworks on Windows that start executables (Go appears to be included in this) you get in trouble when trying to concatenate your own arguments. That is why the args argument for exec.Command is variadic. So your original should have been this:

cmd := exec.Command("cmd", "/C", "start", Filename)
//                         ^^^^^^^^^^^^^^^ variadic arguments make Windows happy
Simon Whitehead
  • 63,300
  • 9
  • 114
  • 138
  • Yes, that works. But what if I want to open a folder or open a text file? – Gordon Truslove Sep 02 '14 at 22:30
  • I included that at the end of the answer in my edit. Windows can be picky about what it chooses to execute through the command prompt given just a file name. You can, of course, execute PDF's and such just fine (as with executables). However, I have found that the foolproof way to open a text file is to pass it as an argument to notepad. With a folder - you pass it as an argument to explorer. – Simon Whitehead Sep 02 '14 at 22:31
  • Thanks for your help, but I'm still struggling. This seems right, cmd := exec.Command("cmd", "/C", "start", Filename) but it opens a command prompt for some reason. Opening a text file was just an example, there are a lot of situations I might need where I need to pass a file name which might have a space in it. – Gordon Truslove Sep 03 '14 at 08:09
  • You have to play around with it per file type to get the right one. To make that easier though - just hit Windows + R and test in the Run dialog. That is essentially the same as running it in Go. – Simon Whitehead Sep 03 '14 at 11:27
  • Windows run works perfectly, because it allows double quotes. I'm going to try to look behind the exec code. I feel like there is a formatting bug. – Gordon Truslove Sep 03 '14 at 11:52
  • I had a quick look while I was at work today and couldn't spot anything out of the ordinary. I would be very interested to know if you find something. What sort of file isn't working for you at the moment? I also found that I didn't need to supply the double quotes... see my code where I commented out that part of your code. – Simon Whitehead Sep 03 '14 at 11:54
  • cmd := exec.Command("cmd", "/C", "start", "C:\a.txt") this works and opens a text file in notepad. cmd := exec.Command("cmd", "/C", "start", "C:\a b.txt") this opens the windows console. – Gordon Truslove Sep 03 '14 at 12:13
  • Go it, but only for windows: exec.Command("rundll32.exe", "url.dll,FileProtocolHandler", Filename) – Gordon Truslove Sep 03 '14 at 12:22
1

This works, but only in windows

cmd := exec.Command("rundll32.exe", "url.dll,FileProtocolHandler", Filename)
Gordon Truslove
  • 724
  • 2
  • 10
  • 19