#!/usr/local/bin/perl -w ###################################################################### # uidfind -- 2005, Mike Schilli ###################################################################### use strict; use File::Find; use Log::Log4perl qw(:easy); use Sysadm::Install qw(:all); use Pod::Usage; use Getopt::Std; my $VERSION = "0.01"; my @ARGV_ORG = @ARGV; getopts("r:iv", \my %opts); my $level = $INFO; $level = $DEBUG if exists $opts{v}; Log::Log4perl->easy_init($level); pod2usage("No start directory given") unless @ARGV; my $start_dir = $ARGV[0]; pod2usage("Not a directory: $start_dir") unless -d $start_dir; my($repl_uid, $repl_gid); if($opts{r}) { if($opts{r} =~ /^\d+$/) { $repl_uid = $opts{r}; } else { ($repl_uid) = (getpwnam($opts{r}))[2]; pod2usage("Unknown user $opts{r}") unless $repl_uid; @ARGV = @ARGV_ORG; sudo_me() unless $> == 0; } ($repl_gid) = (getpwuid($repl_uid))[3]; } find(sub { return if $_ eq "." or $_ eq ".."; my $uid = (stat($_))[4]; DEBUG "Examining $_ ($uid)"; if(my($name) = getpwuid($uid)) { DEBUG "$File::Find::name ($uid/$name) OK"; } else { INFO "$File::Find::name (uid=$uid)"; if($opts{r}) { INFO "Replacing $File::Find::name $uid => $repl_uid/$repl_gid"; if($opts{i}) { my $in = ask("Proceed [Y/n]", "y"); if($in !~ /y/i) { INFO "Skipped $File::Find::name"; return; } } DEBUG "chmod $repl_uid $repl_gid $File::Find::name"; chown $repl_uid, $repl_gid, $_ or LOGDIE "Cannot change $File::Find::name"; } } }, $start_dir); __END__ =head1 NAME uidfind - find files/directories owned by users not in the password file =head1 DOWNLOAD _SRC_HERE_ =head1 SYNOPSIS uidfind [-r replace_by_uid] [-i] start_dir =head1 OPTIONS =over 8 =item B<-r replace_by_uid> Replace all invalid UIDs found by I (can be either a user name or an ID). =item B<-i> (Only in conjunctions with C<-r>). Prompt user each time a replacement is made. =item B<-v> Be verbose. =back =head1 DESCRIPTION uidfind starts a I at C, and searches recursively for files/directories with user IDs not listed in the password file. To replace these unknown IDs by others, use the C<-r> option. To prompt the user interactively before a replacement is made, use C<-i>. =head1 EXAMPLES $ uidfind /home/joe $ uidfind -r joe /home/joe $ uidfind -r joe -i /home/joe =head1 LEGALESE Copyright 2005 by Mike Schilli, all rights reserved. This program is free software, you can redistribute it and/or modify it under the same terms as Perl itself. =head1 AUTHOR 2005, Mike Schilli