====== Selective CHMOD in Perl with pattern matching ======
{{tag>perl debian}}
Simple problems can become quite tricky to solve. Recently, I had to give FTP access to a large folder in which I had some private information.
I did not want to reorganize the folder just because of this access, and I was already using group permission that I couldn't change.
[[http://en.wikipedia.org/wiki/There%27s_more_than_one_way_to_do_it|TIMTOWTDI]] applied, I choosed to created a small perl script that would check the name of a folder/file and, if this name matches some predefined pattern, would apply a specific chmod permission to it.
For example: pattern is "doh" and attached permission is "740".
In the list below, directory **todohpoh** and file **azodihazodihdoh** will match and permission **740** will be applied to them.
$ ls -al /tmp
total 64
drwxrwxrwt 13 root root 12288 oct 28 15:57 .
drwxr-xr-x 25 root root 4096 fev 16 2009 ..
-rw-r--r-- 1 julien julien 0 oct 28 15:57 azodihazodihdoh
-rw-r--r-- 1 julien julien 2513 oct 13 14:30 dokulist
drwxr-xr-x 2 julien julien 4096 oct 27 18:18 prv
drwxr-xr-x 2 alfresco hugetlb 4096 oct 27 10:46 sv728.tmp
drwxr-xr-x 2 julien julien 4096 oct 28 15:57 todohpoh
drwxrwxrwt 2 root root 4096 oct 12 07:58 .X11-unix
drwxr-xr-x 2 julien julien 4096 oct 27 18:19 xxXXprvfdz
drwxr-xr-x 2 julien julien 4096 oct 27 18:19 xxzzzazzdazd
* __Program__: chmod_selected_folders.pl
* __OS__ : Debian Lenny - Linux 2.6.26-1-686 #1 SMP
* __Tested on__: v5.10.0 built for i486-linux-gnu-thread-multi
#! /usr/bin/perl -w
use strict;
# julien vehent - oct. 2009
# browse a list of folder and change the permission
# according to a defined list of patterns and perms
# perm_list contain pattern + associated chmod perm (user|group|others)
# the first pattern that matches is the one applied
# "default" is mandatory and applied when no pattern match the entry
#
my %perm_list = (
"prv" => "770",
"default"=> "775"
);
my $verbose = 0;
sub check_recursively
{
my $folder_name = $_[0];
print "entering $folder_name\n";
# open folder and loop on each entry
opendir my($folder), $folder_name or die "Couldn't open $folder_name: $!\n";
for my $entry (readdir($folder))
{
if(($entry eq ".") or ($entry eq ".."))
{
next;
}
my $entry_chmoded = 0;
my $entry_full_path = $folder_name."/".$entry;
# check entry with all patterns, except default
foreach my $pattern (keys %perm_list)
{
# entry matches pattern, apply corresponding chmod and mark entry
if (($entry =~ /$pattern/) and ($pattern ne "default"))
{
print "$pattern matches -> chmod $perm_list{$pattern} $entry_full_path\n" if $verbose == 1;
system("chmod $perm_list{$pattern} \"$entry_full_path\"");
$entry_chmoded = 1;
}
}
# entry didn't match any pattern, apply default permission
if($entry_chmoded == 0)
{
print "default -> chmod $perm_list{'default'} $entry_full_path\n" if $verbose == 1;
system("chmod $perm_list{'default'} \"$entry_full_path\"");
}
#if entry is a folder, go visit it
if ((-d $entry_full_path) and ($entry ne ".") and ($entry ne ".."))
{
check_recursively($entry_full_path);
}
}
closedir($folder);
}
#--- MAIN CODE ---
unless(defined @ARGV)
{
print "\nchmod_selected_folders.pl\njve - oct.2009\n\nusage: ./chmod_selected_folders.pl ... \n\n";
}
print "using perm list:\n";
foreach my $pattern (keys %perm_list)
{
print " * pattern $pattern will be applied permission $perm_list{$pattern}\n";
}
# list of folder in stdin, loop on it
foreach my $folder_name (@ARGV)
{
print "processing entries starting at $folder_name\n";
check_recursively($folder_name);
}
If no pattern matches an entry, the one called **default** will be applied to it.