Check if there is something to read on STDIN in Golang

后端 未结 4 1815
天涯浪人
天涯浪人 2020-12-08 02:55

I need a command line utility to behave different if some string is piped into its STDIN. Here\'s some minimal example:

package main // file test.go

import          


        
相关标签:
4条回答
  • 2020-12-08 03:16

    Use the IsTerminal function from code.google.com/p/go.crypto/ssh/terminal (which was exp/terminal) or the Isatty function from github.com/andrew-d/go-termutil which is a much more focussed package.

    If stdin is a terminal/tty then you aren't being piped stuff and you can do something different.

    Here is an example

    package main
    
    import (
        "fmt"
        termutil "github.com/andrew-d/go-termutil"
        "io"
        "os"
    )
    
    func main() {
        if termutil.Isatty(os.Stdin.Fd()) {
            fmt.Println("Nothing on STDIN")
        } else {
            fmt.Println("Something on STDIN")
            io.Copy(os.Stdout, os.Stdin)
        }
    }
    

    Testing

    $ ./isatty 
    Nothing on STDIN
    $ echo "hello" | ./isatty 
    Something on STDIN
    hello
    $ (sleep 1 ; echo "hello") | ./isatty 
    Something on STDIN
    hello
    
    0 讨论(0)
  • 2020-12-08 03:31

    I solved this by using os.ModeCharDevice:

    stat, _ := os.Stdin.Stat()
    if (stat.Mode() & os.ModeCharDevice) == 0 {
        fmt.Println("data is being piped to stdin")
    } else {
        fmt.Println("stdin is from a terminal")
    }
    
    0 讨论(0)
  • 2020-12-08 03:32

    This does it:

    package main // file test.go
    
    import (
        "bufio"
    "fmt"
        "os"
    )
    
    func main() {
        in := bufio.NewReader(os.Stdin)
        stats, err := os.Stdin.Stat()
        if err != nil {
            fmt.Println("file.Stat()", err)
        }
    
        if stats.Size() > 0 {
            in, _, err := in.ReadLine()
            if err != nil {
                fmt.Println("reader.ReadLine()", err)
            }
            fmt.Println("Something on STDIN: " + string(in))
        } else {
            fmt.Println("Nothing on STDIN")
        }
    }
    

    Thanks @Kluyg !

    0 讨论(0)
  • 2020-12-08 03:36

    If none of the above works for you, try this way:

    stat, err := os.Stdin.Stat()
    if err != nil {
        return nil, fmt.Errorf("you have an error in stdin:%s", err)
    }
    if (stat.Mode() & os.ModeNamedPipe) == 0 {
        return nil, errors.New("you should pass smth to stdin")
    }
    

    It worked for me in both darwin (Mac OS) and linux (Ubuntu).

    0 讨论(0)
提交回复
热议问题