how to pipe the output from exec.Command into another commands stdin (psql insert command in Golang

2,617 views
Skip to first unread message

Abdo Ruzaqi

unread,
Sep 19, 2015, 10:44:51 AM9/19/15
to golang-nuts
Hi Guys!
I have eight Microsoft access databases each one has around 215 tables and I needed to transfered those databases into postgresql so i used mdb-tools and exported the schemes which just one step ;but when it come to exporting tables data into postgres directly into postgresql i have to write this command for every single table:

mdb-export -I postgres -q \' myaccessdatabase.mdb table-name | psql -d mydatabase -U postgres -w -h localhost

so I have been trying to write a go command program to do as follows:
1. firstly excute a command to list tables name. which will be the arg of the next command.
2. then start for range looop to excute a command that export tanle data and the output of this command is pipe into the next command.
3. this command is psql which will write the output from the previous command ( which is sql insert statment)

package main

import (
    "bufio"
    "log"
    "os"
    "os/exec"
)
func main() {
    // command to Collect tables name and list it to the next command
          tablesname := exec.Command("mdb-tables", "-1", "myaccessdatabase.mdb")

    // Run the command on each table name and get the output pipe/feed into the psql shell
    for _, table := range tablesname {
        ls := exec.Command("mdb-export", "-I", "postgres", "-q", "\'", "myaccessdatabase.mdb", table)

        // | psql -d mydatabase -U postgres -w -h localhost command which will write each line from the output of previouse command's
        visible := exec.Command("psql", "-d", "mypsqldatabase", "-U", "postgres", "-w", "-h", "localhost")


       
    }
}


So i have tried to pipe the output into the stdin of the next command and couldn't implement it , meanwhile I am trying with goroutin and channels just been unable to even come with a way to make this into the last command.

Thank you very much in advance.


silviu...@gmail.com

unread,
Sep 19, 2015, 11:00:05 AM9/19/15
to golang-nuts
Hi, have a look at this package in case it helps your task at hand: https://labix.org/pipe

brainman

unread,
Sep 20, 2015, 9:12:12 PM9/20/15
to golang-nuts
> So i have tried to pipe the output into the stdin of the next command and couldn't implement it ...

If you want to use Windows shell (pipe command | is implemented by Windows cmd.exe), you must execute cmd.exe command instead. For example:
```
C:\dev\src\a>type foo.go
package main

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

func main() {
        output, err := exec.Command("cmd", "/c", "go env | findstr GOROOT").CombinedOutput()
        if err != nil {
                log.Fatalf("command failed: %v %q\n", err, string(output))
        }
        fmt.Printf("%s", output)
}

C:\dev\src\a>go run foo.go
set GOROOT=c:\dev\go

C:\dev\src\a>
```

Alex

James Aguilar

unread,
Sep 20, 2015, 11:37:38 PM9/20/15
to golang-nuts
This is not correct. Shelling out isn't required. You can use io.Copy to copy from one command's stdout pipe to the next command's stdin pipe. Or you can use a library that does this for you like the pipe library provided by the prior respondent.

-- James

Peter Waller

unread,
Sep 21, 2015, 5:08:34 AM9/21/15
to James Aguilar, golang-nuts
I'm surprised this hasn't been mentioned yet. This can be done using an os.Pipe:

http://golang.org/pkg/os/#Pipe

And assign the write side to the cmd.Std{out,err} (whatever you need) and the read side to cmd1.Stdin.

This has the benefit that you're not copying the output bytes through your program - the OS handles it - and that you don't need an external dependency like labix.org/pipe.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Shawn Milochik

unread,
Sep 21, 2015, 10:35:35 AM9/21/15
to golan...@googlegroups.com
This can be done with the StdinPipe() method in the standard library:


Nothing external needed.

Michael Jones

unread,
Sep 21, 2015, 1:09:43 PM9/21/15
to Sh...@milochik.com, golan...@googlegroups.com
This would make a very good example in the documentation.

— 
Michael Jones, CEO  •  mic...@wearality.com  •  +1 650 656-6989 
Wearality Corporation  •  289 S. San Antonio Road  •  Los Altos, CA 94022

Shawn Milochik

unread,
Sep 21, 2015, 1:17:53 PM9/21/15
to golan...@googlegroups.com
On Mon, Sep 21, 2015 at 1:09 PM, Michael Jones <m...@wearality.com> wrote:
This would make a very good example in the documentation.

— 
Michael Jones, CEO  •  mic...@wearality.com  •  +1 650 656-6989 
Wearality Corporation  •  289 S. San Antonio Road  •  Los Altos, CA 94022

On Sep 21, 2015, at 7:34 AM, Shawn Milochik <shawn...@gmail.com> wrote:

This can be done with the StdinPipe() method in the standard library:


Nothing external needed.


There is an example of this in the docs. It's not quite as simple as mine, because it throws in a struct and JSON, but it's readable.



Reply all
Reply to author
Forward
0 new messages