perlstdoutttyfilehandle

What is the difference between writing to STDOUT and a filehandle opened to "/dev/tty"?


What are the differences between this two examples?

#!/usr/bin/perl
use warnings;
use 5.012;
my $str = "\x{263a}";


open my $tty, '>:encoding(utf8)', '/dev/tty' or die $!;
say $tty $str;
close $tty;

open $tty, '>:bytes', '/dev/tty' or die $!;
say $tty $str;
close $tty;

# -------------------------------------------------------

binmode STDOUT, ':encoding(utf8)' or die $!;
say $str;

binmode STDOUT, ':bytes' or die $!;
say $str;

Solution

  • The difference is that you are writing to two distinct and (from Perl's and your program's point of view) independent file handles.

    They may SEEM to be identical at first glance due to the fact that, in a typical situation, a Unix shell will by default associate its file descriptor #1 (and thus one of every process it launches without redirects) with /dev/tty.

    The two have nothing in common from Perl point of view, OTHER than the fact that those two commonly end up associated by default due to the way Unix shells work.

    The functional behavior of the two quoted pieces of code will often SEEM identical due to this default, but that is just "by accident".

    Among practical differences:


    You can CHECK whether your STDOUT is connected to a tty by using the -t operator:

    if ( -t STDOUT ) { say 'STDOUT is connected to a tty' }
    

    As another aside, please note that you CAN make sure that your STDOUT writes to /dev/tty by explicitly closing the STDOUT filehandle and re-opening it to point to /dev/tty:

    close STDOUT or die $!;
    open STDOUT '>:encoding(utf8)', '/dev/tty' or die $!;