首页 > 解决方案 > Is there a way to find out the name of the file stdout is redirected to in Perl?

问题描述

Same question as this one written for Python, but asking again for Perl since - well - they are different scripting languages and perhaps different feature sets.

In general, I want to detect if my Perl script's STDIN our STDOUT is being redirected (preferably the former). Instead of knowing the filename, I'd rather want to know if the caller is using redirection so that I can present them with a 'help text' if they're not.

Preferably platform independent, but I only foresee this script being run on macOS or Linux.

标签: perl

解决方案


您可以检查句柄是否是终端或不使用-t.

if (-t STDOUT) {
   say "Terminal";
} else {
   say "Not a terminal or an error occured"; 
}

或者

defined( my $rv = -t STDOUT )
   or die("Can't check if STDOUT is a terminal: $!\n");

if ($rv) {
   say "Terminal";
} else {
   say "Not a terminal"; 
}

终端与否,您可以找出它的文件类型。

stat(STDOUT)
   or die("Can't stat STDOUT: $!\n");

if    (-f _) { say "Plain file";       }
elsif (-p _) { say "Pipe";             }
elsif (-S _) { say "Socket";           }
elsif (-c _) { say "Character device"; }
elsif (-b _) { say "Block device";     }
else         { say "Something exotic"; }  # Impossible?

终端将是字符设备,但并非所有字符设备都是终端。


除了模块之外,不可能以与系统无关的方式(如果有的话)确定与哪个文件关联(如果它甚至有名称)。

在 Linux 上,您可以使用/proc

$ perl -e'warn readlink("/proc/$$/fd/".fileno(STDOUT))."\n"'
/dev/pts/0

$ perl -e'warn readlink("/proc/$$/fd/".fileno(STDOUT))."\n"' >a
/tmp/ikegami/a

$ perl -e'unlink "a";
          warn readlink("/proc/$$/fd/".fileno(STDOUT))."\n"' >a
/tmp/ikegami/a (deleted)

$ perl -e'warn readlink("/proc/$$/fd/".fileno(STDOUT))."\n"' |cat
pipe:[27807]

推荐阅读