31

How to run a simple Windows command?

This command:

exec.Command("del", "c:\\aaa.txt")

.. outputs this message:

del: executable file not found in %path%

What am I doing wrong?

Rene Knop
  • 1,788
  • 3
  • 15
  • 27
Yster
  • 3,147
  • 5
  • 32
  • 48
  • Please don't refer to commands like `DIR` or `RM` as DOS commands. The ones you want to use are Windows terminal/console commands. If you really wanted to use DOS `RM` command, you'd have to use `ntvdm.exe`, Windows **NT V**irtual **D**OS **M**achine – stacker-baka Mar 26 '18 at 11:49

7 Answers7

57

I got the same error as you. But dystroy is correct: You can't run del or any other command built into cmd because there is no del.exe file (or any other del-executable for that matter).

I got it to work with:

package main
    
import(
    "fmt"
    "os/exec"
)
    
func main() {
    var c *exec.Cmd

    switch runtime.GOOS{
    case "windows":
        c = exec.Command("cmd", "/C", "del", "D:\\a.txt")

    default://Mac & Linux
        c = exec.Command("rm", "-f", "/d/a.txt")
    }

    if err := c.Run(); err != nil { 
        fmt.Println("Error: ", err)
    }
}
b01
  • 4,076
  • 2
  • 30
  • 30
ANisus
  • 74,460
  • 29
  • 162
  • 158
  • What if i would want to use that on mac os? something like `cmd := exec.Command("cmd", "killall opera")` Doesn't work for me. – Alessandro Resta Jun 16 '15 at 10:07
  • on a mac something like `command := exec.Command("bash", "-c", "")` will work – ffel Jul 16 '15 at 11:40
  • 1
    @user2179522 "/C" means `cmd` should carry out the following command and then terminate; in this case "del". But it could be any built-in command. – ANisus Sep 03 '15 at 06:37
  • Thanks ANisus, to add on, we can print the output on command line by converting to string – Rjain Jun 08 '16 at 15:49
  • 2
    Just in case it wasn't clear from the answer, `cmd` commands will not run without the `/C` argument. – freb Oct 12 '16 at 19:04
8

You need a Windows cmd to execute your dir command.

Try this :

cmd := exec.Command("cmd", "/C", "dir").Output()

(sorry, no Windows computer to check it right now)

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • Hi dystroy. I tried it and variations on it, but it doesn't seem to work. It runs, but nothing happens. For instance: exec.Command("cmd /c del c:\\bbb\\aaa.txt") . Thanks for trying. – Yster Oct 22 '12 at 12:21
  • 2
    Since you are deleting from C:, make sure you run your Go-program with privileges to delete from C: – ANisus Oct 22 '12 at 14:27
  • It doesn't work, I received an error: `multiple-value exec.Command("cmd", "/C dir").Output() in single-value contextgo`. You need to add `cmd, err :=` to catch multiple-value. – E235 Jul 16 '19 at 14:36
3

Found another solution too. Create a batch file that contains the following: del c:\aaa.txt

Then call it like this:

exec.Command("c:\\del.bat").Run()
Yster
  • 3,147
  • 5
  • 32
  • 48
2

In case you need the output of cmd:

if c, err := exec.Command("cmd","/c","del","a.txt").CombinedOutput(); err != nil {
        log.Fatal(err)
    } else {
        fmt.Printf("%s\n", c)
    }
1

Ok let's see, according to the documentation, in windows, processes receive commands as a single line string and do some parsing of their own. Exec's Command function builds the command string by combining all arguments together using CommandLineToArgvW, that despite being the most common quoting algorithm doesn't work for every application. Applications like msiexec.exe and cmd.exe use an incompatible unquoting algorithm, hence the extra mile. Heres a different example using powershell

package main

import (
        "os/exec"
        "fmt"
        "log"
        )
func main() {
     out, err := exec.Command("powershell","remove-item","aaa.txt").Output()
     if err != nil {
         log.Fatal(err)
     } else {
         fmt.Printf("%s",out)
     }
1

you can try use github.com/go-cmd/cmd module.
because golang can not use syscall by default.

example:

import (
    "fmt"
    "time"
    "github.com/go-cmd/cmd"
)

func main() {
    // Start a long-running process, capture stdout and stderr
    findCmd := cmd.NewCmd("find", "/", "--name", "needle")
    statusChan := findCmd.Start() // non-blocking

    ticker := time.NewTicker(2 * time.Second)

    // Print last line of stdout every 2s
    go func() {
        for range ticker.C {
            status := findCmd.Status()
            n := len(status.Stdout)
            fmt.Println(status.Stdout[n-1])
        }
    }()

    // Stop command after 1 hour
    go func() {
        <-time.After(1 * time.Hour)
        findCmd.Stop()
    }()

    // Check if command is done
    select {
    case finalStatus := <-statusChan:
        // done
    default:
        // no, still running
    }

    // Block waiting for command to exit, be stopped, or be killed
    finalStatus := <-statusChan
}
1
 c := exec.Command("cmd", "/C", "dir", "d:\\")
    c.Stdin = os.Stdin
    c.Stdout = os.Stdout
    c.Stderr = os.Stderr
    c.Run()