17

Is there a way to detect if a command in go is piped or not?

Example:

cat test.txt | mygocommand #Piped, this is how it should be used
mygocommand # Not piped, this should be blocked

I'm reading from the Stdin reader := bufio.NewReader(os.Stdin).

Florian
  • 271
  • 3
  • 7
  • 1
    Why do you want to block that? Is it actually a *problem* if someone types the input into their terminal manually, or maybe copy-pastes it or something? – user2357112 May 12 '17 at 22:42
  • 1
    Maybe you've seen this already, but here's a parallel line of questioning for shell scripts: http://stackoverflow.com/questions/911168/how-to-detect-if-my-shell-script-is-running-through-a-pipe – user513951 May 12 '17 at 22:43
  • @user2357112 The users input will never end, because there won't be an EOF, will it? – Florian May 12 '17 at 23:13
  • @Florian: Ctrl-D, or Ctrl-Z Enter at the beginning of a line on Windows. – user2357112 May 12 '17 at 23:17

2 Answers2

22

Use os.Stdin.Stat().

package main

import (
  "fmt"
  "os"
)

func main() {
    fi, _ := os.Stdin.Stat()

    if (fi.Mode() & os.ModeCharDevice) == 0 {
        fmt.Println("data is from pipe")
    } else {
        fmt.Println("data is from terminal")
    }
}

(Adapted from this tutorial)

user513951
  • 12,445
  • 7
  • 65
  • 82
1

same can be done with performing a similar bitwise operation with ModeNamedPipe

package main

import (
        "fmt"
        "os"
)

func main() {
        fi, err := os.Stdin.Stat()
        if err != nil {
                panic(err)
        }

        if (fi.Mode() & os.ModeNamedPipe) != 0 {
                fmt.Println("data is from pipe")
        } else {
                fmt.Println("data is from terminal")
        }
}
user513951
  • 12,445
  • 7
  • 65
  • 82