6

I'm currently trying to execute a simple echo command in Golang on Linux. My code is the following:

cmd = exec.Command("echo", "\"foo 0x50\"", ">", "test.txt")

_, err = cmd.Output()

if err != nil {
    fmt.Println(err)
}

But test.txt doesn't appear in my folder (even after compile and run the code). That not the first that that I use this method to execute commands and I never thought that I will be block on an echo command.

So how can I fix this code in order to have "foo 0x50" (with the quotes) in the test.txt?

3 Answers 3

7

You can redirect the stdout like this:

// Remove the redirect from command
cmd := exec.Command("echo", "\"foo 0x50\"")

// Make test file
testFile, err := os.Create("test.txt")
if err != nil {
    panic(err)
}
defer outfile.Close()

// Redirect the output here (this is the key part)
cmd.Stdout = testFile

err = cmd.Start(); if err != nil {
    panic(err)
}
cmd.Wait()
Sign up to request clarification or add additional context in comments.

7 Comments

Okay! but why I can't do it on one line like I tried at the beginning ?
@Majonsi, sort of yes -- you just have to know that those >, <, | etc are interpreted by your shell, and the OS kernel into which exec.Cmd.Run shovels the process specification knows nothing about them. So one way to have that "in one line" is to exec /bin/sh -c "echo blah blah >file.txt", so that not /bin/echo is spawned but a shell which is then told to execute a specific script. The shell parses out that redirection from the script and arrange for them to happen.
@Majonsi, please note that while that would work, you have to think thrice (or more) before treading that route: as soon as you need to encode some data which might contain single or double quotes or redirection symbols or whatnot you enter the quoting hell. Much worse is the situation when you need to pass to the command you're executing some data acquired from the user: you will have to protect it properly from being interpreted by the shell, and that means wandering through that quoting hell being chest-deep in it. Better don't, really.
@Majonsi, In your particular case, the code by Tyler could have been wrapped into a single function. If you want this stuff be more flexibe, better use a special battle-tested library for this: labix.org/pipe
Okay! Thanks for the great explanation and solution. Can you post your answer in order to accept it as a solution?
|
1

For anyone who wants to pass the complete command in oneline/string ,

func call(command string) {
    cmd := exec.Command("sudo", "bash", "-c", command)
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    err := cmd.Start()
    if err != nil {
      fmt.Println(err)
    }
    err1 := cmd.Wait()
    if err1 != nil {
      fmt.Println(err1)
    }
 }

The Wait waits for the command to exit and waits for any copying to stdin or copying from stdout or stderr to complete. It closes the pipe after seeing the command exit.

Sources :

https://stackoverflow.com/a/43246464/9892358

https://stackoverflow.com/a/43246464/9892358

https://zetcode.com/golang/exec-command/

Comments

0
cmd = exec.Command("/bin/bash", "-c", "echo \"foo 0x50\" > test.txt")

_, err = cmd.Output()

if err != nil {
    fmt.Println(err)
}

1 Comment

Thank you for contributing to the Stack Overflow community. This may be a correct answer, but it’d be really useful to provide additional explanation of your code so developers can understand your reasoning. This is especially useful for new developers who aren’t as familiar with the syntax or struggling to understand the concepts. Would you kindly edit your answer to include additional details for the benefit of the community?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.