How can I detect the operating system in Perl?
PerlCross PlatformPerl Problem Overview
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.
Perl Solutions
Solution 1 - Perl
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.
Solution 2 - Perl
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();
Solution 3 - Perl
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.
Solution 4 - Perl
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");
Solution 5 - Perl
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.
Solution 6 - Perl
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.
Solution 7 - Perl
A classic one-liner:
my $windows=($^O=~/Win/)?1:0;# Are we running on windows?
Solution 8 - Perl
FYI on Mac computers $^O now returns 'darwin' for 10.13.6 (High Sierra) and 10.15.4 (Catalina).
Solution 9 - Perl
#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;
Solution 10 - Perl
For a generic mapping in a pre-packaged perl module, check out Perl::OSType
.
It's used by Module::Build
.
Solution 11 - Perl
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"