in reply to Limitations to chmod and performance

Hi,

We had a slew of directories that were created with the wrong permissions on a few of our servers recently. In an effort to make our admin's life a little easier I whipped up this bulk permissions changing script.

It doesn't do exactly what you want, but it might give you a head start. It recurses through the directory trees offering to change any to mode 755 that are set something else. A nice feature is the verbose logging and the creation of a bash friendly undo script when it's done.

Parts of this code were from when I was a younger, less-wise monk so I don't use Getopts or File::Find - but this isn't terribly complicated so it doesn't hurt anything. If you are going to start your own from scratch you'd be wise to check those out. It also doesn't bother with checking the owner since root happened to own all files in this particular case.

Good luck! Click on the READMORE tag for the code.

#! /usr/local/bin/perl -w # # recurse755dir.pl ############################################################## # A simple program to recurse directories and make sure that # # any directories owned by the user are mode 755. # ############################################################## use strict; use Cwd; # Get the current working directory ############# # Variables # ############# my $args = ""; # to parse arguments my $confirm = 1; # confirm = 1, no confirm = 2 my $dirname = ""; # a scalar to hold the filename # Accept a directory as an argument to begin parsing on, # else assume ./ $args = "\t" . ( join "\t", @ARGV ) . "\t"; if ( $args =~ /\t-h\t/ ) { &print_usage(); } if ( $args =~ /\t-nc\t/ ) { print STDERR "Confirm is turned off!\n"; $confirm = 0; } if ( $args =~ /\t([^\t]+?)\t$/ ) { if ( -d $1 ) { $dirname = getcwd . "/$1"; $dirname =~ s'/$''; } else { &print_usage("The supplied argument was not a directory: >$1<" +); } } else { $dirname = getcwd; } print "Welcome to $0\n\n"; print "This program will recurse through your directory structure and +prompt you\n"; print "to change your directory permissions to 755. Every attempt wil +l be made\n"; print "to accurately log the actions performed and to create an UNDO f +ile. If\n"; print "you agree to do this please type in \"yes\" now: "; chomp( my $answer = <STDIN> ); &print_usage("You changed your mind") if ( $answer ne "yes" ); if ( !$confirm ) { print "You have also selected to turn off confirmation! This is a +dumb idea, but\n"; print "if you would like to proceed type in \"yes\" now :"; chomp( $answer = <STDIN> ); &print_usage("You wisely decided not to run in unconfirm mode") if + ( $answer ne "yes" ); } # Two arrays - one will store the work done, one will store the undo i +nformation my ( @log, @undo ); push @log, "+-- recurse755dir began --+\n"; push @undo, "cd " . getcwd . "\n"; &recurse_dirs( $dirname, $confirm, \@log, \@undo ); push @log, "+-- recurse755dir ended --+\n"; # Save the two arrays to disk open( FILEHANDLE, ">>recurse755dir.log" ) or &print_usage("Could not o +pen log"); print FILEHANDLE join "", @log; close(FILEHANDLE); open( FILEHANDLE, ">>recurse755dir.UNDO" ) or &print_usage("Could not +open log"); print FILEHANDLE join "", @undo; close(FILEHANDLE); exit; sub recurse_dirs { my ( $dir, $confirm, $logref, $undoref ) = @_; my ( $mode, @contents ); my $answer = "N"; # Converts the mode returned into a standard format $mode = sprintf( "%04o", ( stat($dir) )[2] & 07777 ); return if ( !-d _ ); push @$logref, "| $dir : $mode\n"; if ( $mode ne "0755" ) { if ($confirm) { print "$dir is mode $mode, change (y/N)? "; chomp( $answer = <STDIN> ); } else { $answer = "y"; } if ( $answer eq "y" ) { push @$logref, "+-" . "-" x ( length($dir) ) . " : 0755\n" +; push @$undoref, "chmod $mode $dir\n"; chmod 0755, $dir; } } opendir DIRHANDLE, $dir; @contents = readdir(DIRHANDLE); closedir DIRHANDLE; foreach (@contents) { next if /^\.+$/; # Skip ./ and ../ &recurse_dirs( "$dir/$_", $confirm, $logref, $undoref ); } } sub print_usage { my $message = shift; if ( defined($message) && ( $message ne "" ) ) { print "$message\n\n"; } print "$0 <-h> <-nc> <directory/path>\n"; print "\n"; print "This program recurses directories and prompts to change the +ir mode\n"; print "to 755. Start a level above where you wish to begin the re +curse.\n"; print "\n"; print "usage: $0 -h # print this message\n"; print " $0 /home/mike/lib/perl # make all dirs under this m +ode 0755\n"; print " $0 # start within current dir\n +"; print " $0 -nc # same, but disable confirm +mode change\n"; print "\n"; exit; }
{NULE}
--
http://www.nule.org