PerlZealot has asked for the wisdom of the Perl Monks concerning the following question:

I have a script which finds all the directories within a given directory and stores them in an array. In the original version of the script, I used something like this:
my $dirname=cwd(); my $sys_get_dirs = "ls -l $dirname | egrep \'^d\'"; my @dirlist=`$sys_get_dirs`;
I want to expand the script as a cross-platform script; both Linux and Windows. Is there a Perl function, command, structure - or something - I can employ in my script to somehow "detect" what OS it's running on? Is it something plainly obvious that I'm missing?

Replies are listed 'Best First'.
Re: recognizing OS
by ikegami (Patriarch) on May 02, 2008 at 23:31 UTC
    I hope noone runs your script from a dir named "foo bar" (won't work) or "| rm -rf *" (won't work and has nasty side effects). Why don't you use readdir and -d instead? It'll fix your bug, it'll be faster, it'll use less resources and it'll be portable.
Re: recognizing OS
by FunkyMonk (Bishop) on May 02, 2008 at 23:21 UTC
    See $^O in perlvar:
    The name of the operating system under which this copy of Perl was built, as determined during the configuration process. The value is identical to $Config{'osname'} . See also Config and the -V command-line switch documented in perlrun. In Windows platforms, $^O is not very helpful: since it is always MSWin32 , it doesn't tell the difference between 95/98/ME/NT/2000/XP/CE/.NET. Use Win32::GetOSName() or Win32::GetOSVersion() (see Win32 and perlport) to distinguish between the variants

    Unless I state otherwise, all my code runs with strict and warnings
Re: recognizing OS
by Anonymous Monk on May 03, 2008 at 05:55 UTC

    Although $^O is the literal answer to your question the answer for portability is to use perls internal functions only rather than system calls. That way the port of Perl takes care of the port of you script for you. This could be a lot more terse if desired:

    use Cwd; opendir my $dir, cwd() or die "Can't read ".cwd().": $!\n"; my @contents = readdir $dir; closedir $dir; my @dirs = grep{ -d and $_ ne '.' and $_ ne '..' } @contents; print "DIR $_\n" for @dirs; #my @files= grep{ -f } @contents; #print "FILE $_\n" for @files;

      cwd() can be changed to just '.'

      opendir my $dir, '.' or die "Can't read current directory (".cwd()."): $!\n";

      That applies to the OP too. He could drop $dirname from the command line both simplifying the code and removing his bug.

        use File::Spec; die File::Spec->curdir;
Re: recognizing OS
by Khen1950fx (Canon) on May 03, 2008 at 10:50 UTC
    This will tell you what OS it's running on, and it'll also give you the release number:

    #!/usr/bin/perl use strict; use warnings; use POSIX qw(uname); my ($uname_s, $uname_r) = (POSIX::uname())[0,2]; print "$uname_s\n", "$uname_r\n";
      This isn't portable to systems that are non-POSIX, is it?
        It does work on Strawberry and ActiveState Perl for Windows (tested on 5.8.8 and 5.10.0 of each). I'm not sure on what other non-Unixy platforms it may fail, though.