Reputation: 2310
Bash has a 'magical behavior', if you type 'ls', usually you will get colorful output, but if you redirect the output to a file, the color codes are gone. How to achive this effect using Go. e.g. With the following statement:
fmt.Println("\033[1;34mHello World!\033[0m")
I can see the text in color, but if I pipe the output to a file, the color is preserved, which is NOT what I want.
BTW, this question is mostly not related to Go, I just want to achive the effect in my go program.
Upvotes: 11
Views: 4629
Reputation: 377
If you are just viewing a log file and don't want colors being preserved because it makes logs less readable, note that
less -r logfile
more -r logfile
multitail -cT ANSI logfile
will make these commands display ANSI colors.
There is also a vim plugin which does the same: https://github.com/powerman/vim-plugin-AnsiEsc
For some use cases this could be a simpler solution than upgrading an app to detect whether an output is attached to a tty.
Upvotes: 0
Reputation: 7208
I'm just answering by copying @ptx comment, which is the more canonical answer:
A better approach is to use term.IsTerminal from x/term. It works on windows and is maintained by the golang team
This is to raise visibility, as this answer is portable and doesn't add an external dependency.
package main
import (
"os"
"golang.org/x/term"
)
func main() {
if term.IsTerminal(int(os.Stdout.Fd())) {
// do stuff when we are attached to a tty
} else {
// do stuff when we are not attached
}
}
Upvotes: 11
Reputation: 12393
Bash has a 'magical behavior', if you type 'ls', usually you will get colorful output, but if you redirect the output to a file, the color codes are gone.
It's not Bash feature, it's ls feature. It calls isatty() to check if stdout file descriptor refers to a terminal. In musl libc isatty is implemented like that:
int isatty(int fd)
{
struct winsize wsz;
unsigned long r = syscall(SYS_ioctl, fd, TIOCGWINSZ, &wsz);
if (r == 0) return 1;
if (errno != EBADF) errno = ENOTTY;
return 0;
}
You can use the same method in Go:
package main
import (
"fmt"
"os"
"golang.org/x/sys/unix"
)
func main() {
_, err := unix.IoctlGetWinsize(int(os.Stdout.Fd()), unix.TIOCGWINSZ)
if err != nil {
fmt.Println("Hello World")
} else {
fmt.Println("\033[1;34mHello World!\033[0m")
}
}
Upvotes: 7