如果某个字符串通过管道连接到其STDIN,我需要一个命令行实用程序来表现不同。这是一些最小的例子:
package main // file test.go
import (
"fmt"
"io/ioutil"
"os"
)
func main() {
bytes, _ := ioutil.ReadAll(os.Stdin)
if len(bytes) > 0 {
fmt.Println("Something on STDIN: " + string(bytes))
} else {
fmt.Println("Nothing on STDIN")
}
}
如果您这样称呼它可以正常工作:
echo foo | go run test.go
如果在STDIN上没有任何内容的情况下调用test.go
,那么事情就会停留在......
bytes, _ := ioutil.ReadAll(os.Stdin)
......等待EOF
。
我需要做些什么才能实现这一目标?
提前致谢!
答案 0 :(得分:37)
我通过使用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")
}
答案 1 :(得分:13)
使用IsTerminal中的code.google.com/p/go.crypto/ssh/terminal功能(exp/terminal
)或Isatty中的github.com/andrew-d/go-termutil功能
这是一个更受关注的方案。
如果stdin是终端/ tty,那么你就不是管道式的东西而且你可以做些不同的事情。
这是一个例子
package main
import (
"fmt"
"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)
}
}
测试
$ ./isatty
Nothing on STDIN
$ echo "hello" | ./isatty
Something on STDIN
hello
$ (sleep 1 ; echo "hello") | ./isatty
Something on STDIN
hello
答案 2 :(得分:2)
如果上述方法都不适合您,请尝试以下方式:
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")
}
它在darwin(Mac OS)和linux(Ubuntu)中都适用于我。
答案 3 :(得分:0)
这样做:
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")
}
}
谢谢@Kluyg!