So I have been playing around with perl the last week and trying to get a handle on it. Im hardly able to write anything decent without having perlmonks or perldoc open though, but I am learning!

Wanted to know what/how I could improve the following code or in what ways you would have done it differently. I really like seeing more than one approach, and I need help pointing out my pitfalls.

Its very simple code, just traverses a specified directory and changes the permissions for files and/or directories. It is my perl way of doing the following with GNU Find.
find [base directory] -type [f|d] -exec chmod [perm] {} \;

Here it is, input greatly appreciated. Im still a newbie though.
#!/usr/bin/perl -w use strict; use Getopt::Long; use File::Find; my %opts = ( verbose => '', directory => './', filemode => '', dirmode => '' ); if(!GetOptions('verbose' => \$opts{'verbose'}, 'filemode:s' => \$opts{'filemode'}, 'dirmode:s' => \$opts{'dirmode'})) { usagedie(); } #make sure each argument passed is either a file or directory foreach (@ARGV) { usagedie() if (!-f || !-d); } #we need to perform at least one option usagedie() if (!$opts{'filemode'} && !$opts{'dirmode'}); #use default directory if argument not set on command line find(\&fileop, $opts{'directory'}) unless @ARGV; find(\&fileop, @ARGV) if @ARGV; sub fileop { #set the right permissions based on if a file or a directory #only set permissions of the mode is set chmod oct($opts{'filemode'}), $_ if -f && $opts{'filemode'}; chmod oct($opts{'dirmode'}), $_ if -d && $opts{'dirmode'}; print $File::Find::name . "\n" if $opts{'verbose'} && (-f || -d); } sub usagedie { print "Usage: setperm.pl [-v] [-f perm] [-d perm] [Directory]\n"; print "-v, --verbose\t show files changed by script\n"; print "-f, --filemode\t octal mode to change files to\n"; print "-d, --dirmode\t octal mode to change directories to\n"; exit(0); }

Updated Code:
#!/usr/bin/perl -w use strict; use Getopt::Long; use File::Find; my %opts = ( verbose => '', filemode => '', dirmode => '' ); if (!GetOptions(\%opts, 'verbose', 'filemode:s', 'dirmode:s')) { usagedie(); } #make sure each argument passed is either a file or directory foreach (@ARGV) { usagedie() if (!-f && !-d); } #we need to perform at least one option usagedie() if (!$opts{'filemode'} && !$opts{'dirmode'}); #make sure correct octal values were used $opts{'filemode'} = chkperm('File', $opts{'filemode'}); $opts{'dirmode'} = chkperm('Directory', $opts{'dirmode'}); #use default directory if argument not set on command line find(\&fileop, @ARGV ? @ARGV : './'); sub fileop { #set the right permissions based on if a file or a directory #only set permissions if the mode is set if (-f && $opts{'filemode'}) { chmod $opts{'filemode'}, $_; } elsif (-d && $opts{'dirmode'}) { chmod $opts{'dirmode'}, $_; } else { #dont print if we didnt modify file perms return; } print $File::Find::name . "\n" if $opts{'verbose'}; } sub chkperm { my ($type, $perm) = @_; #zero length strings are defined values #our $perm 's by default are set to '' if ($perm) { return ($perm =~ /^[0-7]{4}$/) ? oct($perm) : die "Incorrect $type mode $perm\n"; } return; } sub usagedie { print "Usage: setperm.pl [-v] [-f perm] [-d perm] [Directory]\n"; print "-v, --verbose\t show files changed by script\n"; print "-f, --filemode\t octal mode to change files to\n"; print "-d, --dirmode\t octal mode to change directories to\n"; exit(1); }

Thanks to all of ya'll who helped out. I tested it a few times and it worked perfect, I will test more, but I wanted to show what the combined efforts did to the script before it went off the front page.

I'll be adding an exclude option soon too. This will allow you to exclude directories or files. Thanks!

In reply to How would you go about it? by pcassell

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.