HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Perl script for finding all unowned files and directories on Unix

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
scriptunixallperlunownedfilesforfindinganddirectories

Problem

(Originally posted on Stack Overflow)

Following my findings and suggestions in my other post How to exclude a list of full directory paths in find command on Solaris, I have decided to write a Perl version of this script and see how I could optimize it to run faster than a native find command. So far, the results are impressive!

The purpose of this script is to report all unowned files and directories on a Unix system for audit compliance. The script has to accept a list of directories and files to exclude (either by full path or wildcard name), and must take as little processing power as possible. It is meant to be run on hundreds of Unix systems that we (the company I work for) support, and has be able to run on all those Unix systems (multiple OS, multiple platforms: AIX, HP-UX, Solaris and Linux) without us having to install or upgrade anything first. In other words, it has to run with standard libraries and binaries we can expect on all systems.

I have not yet made the script argument-aware, so all arguments are hard-coded in the script. I plan on having the following arguments in the end and will probably use getopts to do it:

-d = comma delimited list of directories to exclude by path name
-w = comma delimited list of directories to exclude by basename or wildcard
-f = comma delimited list of files to exclude by path name
-i = comma delimited list of files to exclude by basename or wildcard
-t:list|count = Defines the type of output I want to see (list of all findinds, or summary with count per directory)


Here is the source I have done so far:

```
#! /usr/bin/perl
use strict;
use File::Find;

# Full paths of directories to prune
my @exclude_dirs = ('/dev','/proc','/home');

# Basenames or wildcard names of directories I want to prune
my $exclude_dirs_wildcard = '.svn';

# Full paths of files I want to ignore
my @exclude_files = ('/tmp/test/dir3/.svn/svn_file1.txt','/tmp/test/dir3/.svn/svn_file2.txt');

# Basenames of wildcard names of files I wa

Solution

Overall it looks clean and simple. Good job. Here are some things I noticed:

  • You should use use warnings for production level code. It's odd that you use strict but not warnings.



  • List::Util or List::MoreUtils should have a suitable replacement for your in_array() function if you're interested or have it installed on all your systems.



  • If you're using a Perl version >= 5.10, you can replace in_array with the smart match operator ~~.



  • Don't let your exclude lists get too big as storing them in an array an iterating through them is an O(n) operation. A hash lookup may be faster for large lists and would de-dup for you automatically.



  • Using & before calling a sub is pretty much deprecated. Just call it directly.



  • The shebang line /usr/bin/env perl is more portable than /usr/bin/perl



  • You stat your file $name over and over for all your various tests. stat() it once, save the results, then re-use those results for all your tests. Remember that all tests like -d, -l and -f are stat() calls internally. Read up on the Perl stat call and all the fields to help determine how to re-create the -d, -l, and -f checks against the returned data.

Context

StackExchange Code Review Q#5545, answer score: 5

Revisions (0)

No revisions yet.