59
votes

I have Perl on Mac, Windows and Ubuntu. How can I tell from within the script which one is which? Thanks in advance.

Edit: I was asked what I am doing. It is a script, part of our cross-platform build system. The script recurses directories and figures out what files to build. Some files are platform-specific, and thus, on Linux I don't want to build the files ending with _win.cpp, etc.

11
Why do you need to know? [There may be a more appropriate answer to your question, depending on what (if anything) it is you're doing that's platform-dependant.] - Rob

11 Answers

86
votes

Examine the $^O variable which will contain the name of the operating system:

print "$^O\n";

Which prints linux on Linux and MSWin32 on Windows.

You can also refer to this variable by the name $OSNAME if you use the English module:

use English qw' -no_match_vars ';
print "$OSNAME\n";

According to perlport, $^O will be darwin on Mac OS X.


You can also use the Config core module, which can provide the same information (and a lot more):

use Config;

print "$Config{osname}\n";
print "$Config{archname}\n";

Which on my Ubuntu machine prints:

linux
i486-linux-gnu-thread-multi

Note that this information is based on the system that Perl was built, which is not necessarily the system Perl is currently running on (the same is true for $^O and $OSNAME); the OS won't likely be different but some information, like the architecture name, may very well be.

14
votes

If you need more specific information on Windows this may help.

my $osname = $^O;


if( $osname eq 'MSWin32' ){{
  eval { require Win32; } or last;
  $osname = Win32::GetOSName();

  # work around for historical reasons
  $osname = 'WinXP' if $osname =~ /^WinXP/;
}}

Derived from sysinfo.t, which I wrote the original version.

If you need more detailed information:

my ( $osvername, $major, $minor, $id ) = Win32::GetOSVersion();
7
votes

Sys::Info::OS looks like a relatively clean potential solution, but currently doesn't seem to support Mac. It shouldn't be too much work to add that though.

7
votes

Look inside the source for File::Spec to see how it loads the right delegate based on the operating system. :)

File::Spec has a separate Perl module file for each OS. File::Spec::Win32, File::Spec::OS2, etc...

It checks the operating system and will load the appropriate .pm file at runtime based on OS.

# From the source code of File::Spec
my %module = (
      MSWin32 => 'Win32',
      os2     => 'OS2',
      VMS     => 'VMS',
      NetWare => 'Win32', # Yes, File::Spec::Win32 works on NetWare.
      symbian => 'Win32', # Yes, File::Spec::Win32 works on symbian.
      dos     => 'OS2',   # Yes, File::Spec::OS2 works on DJGPP.
      cygwin  => 'Cygwin',
      amigaos => 'AmigaOS');


my $module = $module{$^O} || 'Unix';

require "File/Spec/$module.pm";
our @ISA = ("File::Spec::$module");
3
votes

The variable $^O (that's a capital 'O', not a zero) holds the name of the operating system.

Depending on what you want, it may or may not give the answer you want - on my system it gives 'linux' without saying which distro. I'm not so sure about what it says on Windows or MacOS.

2
votes

Here's a quick reference on how to find the OS the local machine is running from Perl.

The $^O variable ($OSTYPE if you use English) contains the operating system that your perl binary was built for.

1
votes

A classic one-liner:

my $windows=($^O=~/Win/)?1:0;# Are we running on windows?
1
votes

FYI on Mac computers $^O now returns 'darwin' for 10.13.6 (High Sierra) and 10.15.4 (Catalina).

0
votes
#Assign the $home_directory variable the path of the user's home directory
my $home_directory = ($^O eq /Win/) ? $ENV{HOMEPATH} : $ENV{HOME};
#Then you can read/write to files in the home directory
open(FILE, ">$home_directory/my_tmp_file");
print FILE "This is a test\n";
close FILE;
#And/or read the contents of the file
open(FILE, "<$home_directory/my_tmp_file");
while (<FILE>){
    print $_;
}
close FILE;
0
votes

For a generic mapping in a pre-packaged perl module, check out Perl::OSType.

It's used by Module::Build.

-3
votes

yes using Config module can be a good thing. One more possibility is getting the info from /etc/*release files

for eg..

cat /etc/os-release

NAME="UBUNTU"
VERSION="12.0.2 LTS, Precise Pangolin"
ID="UBUNTU"
ID_LIKE=debian
PRETTY_NAME="Ubuntu precise (12.0.2 LTS)"
VERSION_ID="12.04"