Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

File Sorting Script

Status
Not open for further replies.

SegFaultAX

Programmer
Oct 12, 2007
2
US
Problem: I have a bunch of files with assorted extensions in a "dump" folder. I want to sort the files into directories according to their extensions. Assume that the extension will ALWAYS be followed by the last period. If there is no period present, then it can either be ignored or moved into some other directory. The directory will be a direct child of the dump dir. If a file is found that has an extension with no corresponding directory, make it, then move it. Under some circumstances, there may be duplicate file names, in which case something like _1 or _2 can be appended to the end.

Question: How difficult would a script like this be to write? Are there any limitations in perl that would make some aspect of this impossible? Can anyone provide examples that would at least give a skeleton for creating a script like this? Any other suggestions or comments?

Thanks in advance!
Cheers, MK
 
Hi SegFaultAx...

What ill do is show you the completed code so far, and then try to explain which part "discovers the present mime types in the dump, then generates the directory(ies)". The script is working well.

Please Note:
1) If you read the other responses they I advised me to improve my code using more efficient looping methods. At the moment my code is similar to ones I posted before (except improved). However, check back tomorrow and I should have posted the improved code.

2) Because I run my scripts from a linux web server, some of my Perl syntax is different (as you know). Therefore I have turned web based syntax into a comment (#####). I have however kept <p> html tags in print statements.

3) If there are no files in the dump and I run the script I recieve an Error 500, although I am not sure why this is.

Here is the complete code:
Code:
#! /usr/bin/perl
use strict;
#####use CGI ':standard'; (ON A WEB BASED SERVER, MUST DECLARE YOU ARE USING CGI STANDARD)
#####print "Content-type: text/html\n\n"; (NO NEED TO DECLARE CONTENT TYPE)
my ($time_date, $forward_slash, $duplicate_file_indicator, $fullstop, $path, $no_mime_folder, @directory_contents, @mime_type_split, $mime_type_split_scaler, @mime_type, $number_of_files, $counter, $move_to_folder, $path_2, $file_name, @file_exist_split, $file_exist_shift, $file_exist_mime);
my ($sec, $min, $hour, $mday, $mon, $year)=gmtime;
$time_date = sprintf ('%02d%02d%02d%02d%02d%02d', $hour, $min, $sec, $mday, $mon, $year);
$forward_slash = "/";
$duplicate_file_indicator = "_$time_date";
$fullstop = ".";
$path = "/ChrisMassey.co.uk/Perl/Scripts/CleanDirectory/Files/";
$no_mime_folder = "NoMimeDump";
opendir (LOGDIR, "$path") || die "Cannot Open: $path";
@directory_contents = readdir (LOGDIR);
closedir (LOGDIR);
#####shift (@directory_contents); (ON A WEB BASED SERVER, SOMETIMES THE FIRST VALUES ARE A . AND A ..) (REMOVES THE .)
#####shift (@directory_contents); (REMOVES THE ..)
$number_of_files = @directory_contents;
if ($number_of_files != 0) {
foreach (@directory_contents) {
if ($_, /\.$/) {
unless (-e "$path$no_mime_folder") {
mkdir ("$path$no_mime_folder", 0777) || die "Cannot Open: $path$no_mime_folder";
}
rename ("$path$_", "$path$no_mime_folder$forward_slash$_") || die "Cannot Open: $path$_ - $path$no_mime_folder$_";
print "<p>$_ has been moved to $path$no_mime_folder";
}
@mime_type_split = split (/\./, $_);
shift (@mime_type_split);
$mime_type_split_scaler = "@mime_type_split";
push @mime_type, $mime_type_split_scaler;
}
foreach (@mime_type) {
unless (-e "$path$_") {
mkdir ("$path$_", 0777) || die "Cannot Open: $path$_";
}
}
$counter = 0;
while ($counter < $number_of_files) {
foreach (@directory_contents) {
$move_to_folder = @mime_type[$counter];
unless (-d "$path$move_to_folder$forward_slash$_") {
$path_2 = $path . $_;
$file_name = $_;
if (-e "$path$move_to_folder$forward_slash$_") {
@file_exist_split = split (/\./, $_);
$file_exist_shift = shift (@file_exist_split);
$file_exist_mime = "@file_exist_split";
shift (@file_exist_split);
$_ = $file_exist_shift . $duplicate_file_indicator . $fullstop . $file_exist_mime;
}
rename ("$path_2", "$path$move_to_folder$forward_slash$_") || die "Cannot Open: $path$_ - $path$move_to_folder";
print "<p>$file_name has been moved to $path$move_to_folder";
$counter++
}
}
}
print "<p>Directory $path Was Empty...";
}
if ($number_of_files == 0) {
#####print "Content-type: text/html\n\n"; (NO NEED TO DECLARE CONTENT TYPE)
print "<p>Process Complete...";
}

What this script does:
Exactly what you wanted it to. Once run, any files in the dump folder (which I have called "Files") will be sorted by mime type (and placed into a folder named by their mime (i.e. "file.txt" would be moved into folder "txt") which is created if it doesn't already exist. If a file doesn't have a mime (i.e. "file.") then the folder "NoMimeDump" will be created and the file moved to there. For ease, if a file has the same name as another, then it is given a time and date stamp so that it has a unique new name.

Now so you understand this part:
"discovers the present mime types in the dump, then generates the directory(ies)"

Its not as simple as just showing you a couple of lines of code, because the entire script is made up of doing this...

Code:
##### After placing the entire directory contents into an array, go through each file and split it using the . as a split point (i.e. file.txt would go into the new array as ('file', 'txt'). $_ is the default variable from the loop (contains each file).

@mime_type_split = split (/\./, $_);

##### Remove the name of the file so you are just left with the mime type (turns ('file', 'txt') into ('txt').

shift (@mime_type_split);

##### Place the remaining contents of the array (which is "txt" onto a scaler variable.

$mime_type_split_scaler = "@mime_type_split";

##### Place the scaler variable onto the end of the mime type array which will be used later to create the mime type folder when sorting the files.

push @mime_type, $mime_type_split_scaler;

##### foreach element in the mime type array.

foreach (@mime_type) {

##### If a folder with that mime type exists then we don't want to overright it.

unless (-e "$path$_") {

##### If the mime folder doesn't already exist then we create it
mkdir ("$path$_", 0777) || die "Cannot Open: $path$_";

##### End unless
}

When I was writing the code, I forgot about alot of the different logical aspects. It was only until i tested it I could see what I was doing wrong. So don't forget about some of the other important processes (for example: checking if files already exist before creating new folders, AND making sure that folders aren't processed etc etc)

I hope this helps. I will work on improving the code hopefully into a single set of loops

Goodluck,

Chris
 
Hello Again,

I have now produced code that is much shorter, and much more efficient. It performs exactly the same task as the above code. The only problem is that if a file has the same name as another, then it isn't renamed and moved. Any suggestions why this is happening?

Code:
#! /usr/bin/perl
use strict;
use CGI ':standard';
###############

##### DECLARE VARIABLES
my ($time_date_stamp, $path, $no_ext_dump, $fullstop, $underslash, @directory_contents, $counter, @split_name_ext, $name, $ext);
##### GET TIME/DATE STAMP
my ($sec, $min, $hour, $mday, $mon, $year)=gmtime;
$time_date_stamp = sprintf ('%02d%02d%02d%02d%02d%02d', $hour, $min, $sec, $mday, $mon, $year);
##### DECLARE CONTENT TYPE
print "Content-type: text/html\n\n";
##### INITIAL VALUES
$path = "/ChrisMassey.co.uk/Perl/Scripts/CleanDirectory/Files/";
$no_ext_dump = "No_Ext";
$fullstop = ".";
$underslash = "_";
##### START COUNTER ON 0
$counter = 0;
##### OPEN PATH DIRECTORY AND GET CONTENTS
opendir (LOGDIR, "$path") || die "Cannot Open: $path";
@directory_contents = readdir (LOGDIR);
closedir (LOGDIR);
##### REMOVE . AND . 
shift (@directory_contents);
shift (@directory_contents);

###############
##### MAIN LOOP
foreach (@directory_contents) {
     if ($_ !~ /\./) {
          unless (-d "$path$_") {
               unless (-e "$path$no_ext_dump") {
                    mkdir ("$path$no_ext_dump", 0777) || die "Cannot Open: $path$no_ext_dump";
               }
               rename ("$path$_", "$path$no_ext_dump/$_") || die "Cannot Open: $path$_ - $path$no_ext_dump/$_";
               print "<p>$_ has been moved to $path$no_ext_dump";
               $counter++
          }
     }
     else {
          @split_name_ext = split (/\./, $_);
          $name = @split_name_ext[0];
          $ext = @split_name_ext[1];
          unless (-e "$path$ext") {
               mkdir ("$path$ext", 0777) || die "Cannot Open: $path$ext";
          }
     }
     unless (-d "$path$_") {
          if (-e "$path$ext/$_") {
               $_ = $name . $underslash . $time_date_stamp . $fullstop . $ext;
          }
          rename ("$path$_", "$path$ext/$_") || die "Cannot Open: $path$_ - $path$ext/$_";
          print "<p>$_ has been moved to $path$ext/$_";
          $counter++
     }
}
##### MAIN LOOP ENDED
###############
print "<p>$counter files have been sorted";

Chris
 
I have changed:
Code:
               unless (-e "$path$no_ext_dump") {
                    mkdir ("$path$no_ext_dump", 0777) || die "Cannot Open: $path$no_ext_dump";
               }
               rename ("$path$_", "$path$no_ext_dump/$_") || die "Cannot Open: $path$_ - $path$no_ext_dump/$_";
               print "<p>$_ has been moved to $path$no_ext_dump";
               $counter++

to:

Code:
               unless (-e "$path$no_ext_dump") {
                    mkdir ("$path$no_ext_dump", 0777) || die "Cannot Open: $path$no_ext_dump";
               }
               if (-e "$path$no_ext_dump/$_") {
                    $_ = $_ . $underslash . $time_date_stamp;
               }
               rename ("$path$_", "$path$no_ext_dump/$_") || die "Cannot Open: $path$_ - $path$no_ext_dump/$_";
               print "<p>$_ has been moved to $path$no_ext_dump";
               $counter++

To check if a file with no extension also already exists.
 
Right I can see where I went wrong. It was whilst renaming a file:
Code:
if (-e "$path$no_ext_dump/$_") {
                    $_ = $_ . $underslash . $time_date_stamp;
               }
rename ("$path$_", "$path$no_ext_dump/$_") || die "Cannot Open: $path$_ - $path$no_ext_dump/

If the file already existed, I changed the name to something different. However, because I change the default vaiable ($_) when I tried to open the old file name to rename it it tried to open the new file name instead. Therefore I had to place the $_ onto another variable before renaming the file.

And the final complete code is...

Code:
#! /usr/bin/perl
use strict;
use CGI ':standard';
###############

##### DECLARE VARIABLES
my ($time_date_stamp, $path, $no_ext_dump, $fullstop, $underslash, @directory_contents, $counter, $file_name, @split_name_ext, $name, $ext);
##### GET TIME/DATE STAMP
my ($sec, $min, $hour, $mday, $mon, $year)=gmtime;
$time_date_stamp = sprintf ('%02d%02d%02d%02d%02d%02d', $hour, $min, $sec, $mday, $mon, $year);
##### DECLARE CONTENT TYPE
print "Content-type: text/html\n\n";
##### INITIAL VALUES
$path = "/kunden/homepages/4/d160423788/htdocs/ChrisMassey.co.uk/Perl/Scripts/CleanDirectory/Files/";
$no_ext_dump = "No_Ext";
$fullstop = ".";
$underslash = "_";
##### START PROCESS COUNTER ON 0
$counter = 0;
##### OPEN PATH DIRECTORY AND GET CONTENTS
opendir (LOGDIR, "$path") || die "Cannot Open: $path";
@directory_contents = readdir (LOGDIR);
closedir (LOGDIR);
##### REMOVE . AND . 
shift (@directory_contents);
shift (@directory_contents);

###############
##### MAIN LOOP
foreach (@directory_contents) {
     if ($_ !~ /\./) {
          unless (-d "$path$_") {
               unless (-e "$path$no_ext_dump") {
                    mkdir ("$path$no_ext_dump", 0777) || die "Cannot Open: $path$no_ext_dump";
               }
               $file_name = $_;
               if (-e "$path$no_ext_dump/$_") {
                    $_ = $_ . $underslash . $time_date_stamp;
               }
               rename ("$path$file_name", "$path$no_ext_dump/$_") || die "Cannot Open: $path$_ - $path$no_ext_dump/$_";
               print "<p>$_ has been moved to $path$no_ext_dump";
               $counter++
          }
     }
     else {
          @split_name_ext = split (/\./, $_);
          $name = @split_name_ext[0];
          $ext = @split_name_ext[1];
          unless (-e "$path$ext") {
               mkdir ("$path$ext", 0777) || die "Cannot Open: $path$ext";
          }
     }
     unless (-d "$path$_") {
          $file_name = $_;
          if (-e "$path$ext/$_") {
               $_ = $name . $underslash . $time_date_stamp . $fullstop . $ext;
          }
          rename ("$path$file_name", "$path$ext/$_") || die "Cannot Open: $path$_ - $path$ext/$_";
          print "<p>$_ has been moved to $path$ext/$_";
          $counter++
     }
}
##### MAIN LOOP ENDED
###############
print "<p>$counter files have been sorted";

Chris
 
Chris,

A couple of things.

What happens if a file is named frog.picture.gif ?

your code will say the extension is .picture:

Code:
          @split_name_ext = split (/\./, $_);
          $name = @split_name_ext[0];
          $ext = @split_name_ext[1];


Also, you are using array slices in your code, @split_name_ext[0], instead of scalars, $split_name_ext[0], which is the correct way to access a single element of an array. Perl still supports the old @array[0] syntax but it is long deprecated and will produce warnings if the -w switch or the "warnings" pragma are being used, and one of them should be used.



------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Hi Kevin,

Thanks for the advice on array slices. The book I learnt from advised to use @array[n], but in future I will use $array[n].

When I was writing the code, I stuck to his guidelines. I assumed that he would never have a file which contains a . within. However, you are right and I should be aware of multiple .'s.

Would you suggest using pop(@split_name_ext) then I could rejoin the remaining elements.. join(/./,@split_name_ext)

and then $_ and $name would be $split_name_ext_new = "@split_name_ext";

Chris
 
Right,

I changed my else statement to:

Code:
else {
          @split_name_ext = split (/\./, $_);
          $ext = $split_name_ext[-1];
          pop (@split_name_ext);
          $name = "@split_name_ext";
          unless (-e "$path$ext") {
               mkdir ("$path$ext", 0777) || die "Cannot Open: $path$ext";
          }
     }

Earlier I made a change to the first statement after the foreach:

Code:
if (($_ !~ /\./) || ($_ =~ /\.$/)) {

However this also needs to be adjusted in order to account for file names that contain a . in them.
 
You're book must be very old. You may want to get a newer one [wink]

Personally, I suggest using File::Basename to get the file name and extension into variables. You can use it for filtering and other uses. But you can use $foo[-1] as a good alternative. But keep in mind that the filename will not be $foo[0] if there are multiple dots in the filename. It is a rare condition to have filenames with dots in them but it is something to be aware of.



------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Yeah I used file::basename earlier this week. It can remove extensions easily with just one line of code. Somebody told me that there is no need to use it for what I was doing, so I have tried to avoid using it. I think because of this line:

if (($_ !~ /\./) || ($_ =~ /\.$/)) {

I have no alternative but to use file::basename. I can't think of a logical way to check if only the filename part contains .'s when sorting files with no extension.

Chris
 
Code:
opendir (LOGDIR, $path) || die "Cannot Open $path: [b]$![/b]";
my @directory_contents = grep {!/^\.{1,2}$/} readdir (LOGDIR);
closedir (LOGDIR);

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Kevin,

my @directory_contents = grep {!/^\.{1,2}$/} readdir (LOGDIR);

Do you mind explaining what the {1,2} does?

Also, I read every file in @directory_contents before I format any of the elements. Therefore, only elements that support the grep condition are read into the array. This means that files that don't support the condition aren't read into the array, therefore some files are ignored? Is this because you suggest that I read the file twice, i.e. once for files with extensions, and once for files that do?

Cheers
 
I now know that {1,2} checks for minimum and maximum occurences (minimum 1, and maximum 2)... But what if the file has more than a maximum of 2 i.e.

Why.Hello.Big.World
or
Why.Hello.Big.World.
or
Why.Hello.Big.World.txt

Chris
 
{1,2} is a quantifier. Means: at least one but not more than 2 of whatever is to the left of it.

{min,max}

My code just gets everything into the array but not '.' and '..'. So you can ignore them later in your code. It would basically replace these lines:

opendir (LOGDIR, "$path") || die "Cannot Open: $path";
@directory_contents = readdir (LOGDIR);
closedir (LOGDIR);
##### REMOVE . AND .
shift (@directory_contents);
shift (@directory_contents);


------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
I now know that {1,2} checks for minimum and maximum occurences (minimum 1, and maximum 2)... But what if the file has more than a maximum of 2 i.e.

it checks for consecutive occurances:

.
..

it does not check for non-consecutive occurances:

this.foo.bar


------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Here is some code I whipped up. It does not check if the file already exists in the destination folder. I leave that up to whoever wants to fgure it out:

Code:
[url=http://perldoc.perl.org/functions/use.html][black][b]use[/b][/black][/url] [green]strict[/green][red];[/red]
[black][b]use[/b][/black] [green]warnings[/green][red];[/red]
[black][b]use[/b][/black] [green]File::Path[/green][red];[/red]
[black][b]use[/b][/black] [green]File::Copy[/green][red];[/red]
[gray][i]# uncomment next line for debugging and sanity checks[/i][/gray]
[gray][i]#use Data::Dumper;[/i][/gray]

[gray][i]# the start directory[/i][/gray]
[url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [blue]$dir[/blue] = [red]'[/red][purple]c:/dump[/purple][red]'[/red][red];[/red]

[gray][i]# a hash to store the filesnames[/i][/gray]
[gray][i]# the keys are the MIME type or file extenstion.[/i][/gray]
[gray][i]# NOEXT is for file with no extension[/i][/gray]
[gray][i]# SUSPECT is for file extensions with none word characters in them. Could be[/i][/gray]
[gray][i]# potentitally dangerous so just move these files into the SUSPECT folder.[/i][/gray]
[black][b]my[/b][/black] [blue]%types[/blue] = [red]([/red] [purple]NOEXT[/purple] => [red][[/red][red]][/red], [purple]SUSPECT[/purple] => [red][[/red][red]][/red] [red])[/red][red];[/red]	

[url=http://perldoc.perl.org/functions/opendir.html][black][b]opendir[/b][/black][/url][red]([/red]DIR, [blue]$dir[/blue][red])[/red] or [url=http://perldoc.perl.org/functions/die.html][black][b]die[/b][/black][/url] [red]"[/red][purple][blue]$![/blue][/purple][red]"[/red][red];[/red]

[olive][b]while[/b][/olive] [red]([/red][black][b]my[/b][/black] [blue]$t[/blue] = [url=http://perldoc.perl.org/functions/readdir.html][black][b]readdir[/b][/black][/url] DIR[red])[/red] [red]{[/red]
   [gray][i]# we only want files[/i][/gray]
   [olive][b]next[/b][/olive] [olive][b]unless[/b][/olive] [red]([/red][url=http://perldoc.perl.org/functions/-X.html][black][b]-f[/b][/black][/url] [red]"[/red][purple][blue]$dir[/blue]/[blue]$t[/blue][/purple][red]"[/red][red])[/red][red];[/red]
   [gray][i]# get the file extension[/i][/gray]
   [olive][b]if[/b][/olive] [red]([/red] [blue]$t[/blue] =~ [red]/[/red][purple][purple][b]\.[/b][/purple]([^.]+)$[/purple][red]/[/red] [red])[/red] [red]{[/red]
      [black][b]my[/b][/black] [blue]$f[/blue] = [blue]$1[/blue][red];[/red]
      [gray][i]# check it for suspicious characters[/i][/gray]
      [olive][b]if[/b][/olive] [red]([/red][blue]$f[/blue] =~ [red]/[/red][purple]^[a-zA-Z0-9_-]+$[/purple][red]/[/red][red])[/red] [red]{[/red]
         [gray][i]# its OK[/i][/gray]
         [url=http://perldoc.perl.org/functions/push.html][black][b]push[/b][/black][/url] [blue]@[/blue][red]{[/red][blue]$types[/blue][red]{[/red][blue]$f[/blue][red]}[/red][red]}[/red], [blue]$t[/blue][red];[/red]
      [red]}[/red]
      [olive][b]else[/b][/olive] [red]{[/red]
         [gray][i]# it's suspicious[/i][/gray]
         [black][b]push[/b][/black] [blue]@[/blue][red]{[/red][blue]$types[/blue][red]{[/red][purple]SUSPECT[/purple][red]}[/red][red]}[/red], [blue]$t[/blue][red];[/red]
      [red]}[/red]
   [red]}[/red]
   [olive][b]else[/b][/olive] [red]{[/red]
      [gray][i]# no file extension[/i][/gray]
      [black][b]push[/b][/black] [blue]@[/blue][red]{[/red][blue]$types[/blue][red]{[/red][purple]NOEXT[/purple][red]}[/red][red]}[/red], [blue]$t[/blue][red];[/red]
   [red]}[/red]
[red]}[/red]
[gray][i]# uncomment next line for sanity checks[/i][/gray]
[gray][i]#print Dumper \%types;[/i][/gray]

[gray][i]# make a list of folders to create [/i][/gray]
[black][b]my[/b][/black] [blue]@folders[/blue] = [url=http://perldoc.perl.org/functions/map.html][black][b]map[/b][/black][/url] [red]{[/red] [red]"[/red][purple][blue]$dir[/blue]/[blue]$_[/blue][/purple][red]"[/red] [red]}[/red] [url=http://perldoc.perl.org/functions/keys.html][black][b]keys[/b][/black][/url] [blue]%types[/blue][red];[/red]

[gray][i]# make the folders[/i][/gray]
[gray][i]# will print a message if folder can't be created[/i][/gray]
[olive][b]for[/b][/olive] [red]([/red] [blue]@folders[/blue] [red])[/red] [red]{[/red]
   [maroon]mkpath[/maroon][red]([/red] [blue]$_[/blue], [red]{[/red][purple]verbose[/purple] => [fuchsia]1[/fuchsia][red]}[/red] [red])[/red] or [url=http://perldoc.perl.org/functions/print.html][black][b]print[/b][/black][/url] [red]"[/red][purple]Could not create [blue]$_[/blue]. Might already exist.[purple][b]\n[/b][/purple][/purple][red]"[/red][red];[/red]
[red]}[/red]

[gray][i]# move the files into the folders[/i][/gray]
[olive][b]foreach[/b][/olive] [black][b]my[/b][/black] [blue]$type[/blue] [red]([/red][black][b]keys[/b][/black] [blue]%types[/blue][red])[/red] [red]{[/red]
   [olive][b]foreach[/b][/olive] [black][b]my[/b][/black] [blue]$file[/blue] [red]([/red] [blue]@[/blue][red]{[/red][blue]$types[/blue][red]{[/red][blue]$type[/blue][red]}[/red][red]}[/red] [red])[/red] [red]{[/red]
      [maroon]move[/maroon][red]([/red][red]"[/red][purple][blue]$dir[/blue]/[blue]$file[/blue][/purple][red]"[/red], [red]"[/red][purple][blue]$dir[/blue]/[blue]$type[/blue]/[blue]$file[/blue][/purple][red]"[/red][red])[/red] or
        [black][b]print[/b][/black] [red]"[/red][purple]move failed [[blue]$dir[/blue]/[blue]$file[/blue], [blue]$dir[/blue]/[blue]$type[/blue]/[blue]$file[/blue]] : [blue]$![/blue][/purple][red]"[/red][red];[/red]
   [red]}[/red]
[red]}[/red]

[black][b]print[/b][/black] [red]"[/red][purple]Finished processing files[/purple][red]"[/red][red];[/red]
[tt]------------------------------------------------------------
Pragmas (perl 5.8.8) used :
[ul]
[li]strict - Perl pragma to restrict unsafe constructs[/li]
[li]warnings - Perl pragma to control optional warnings[/li]
[/ul]
Core (perl 5.8.8) Modules used :
[ul]
[li]File::Copy - Copy files or filehandles[/li]
[li]File::path - create or remove directory trees[/li]
[/ul]
[/tt]

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Ah I see,

next if $file =~ /^\.\.?$/;
[/quote

Was the suggestion by travs which i forgot about. I have now included that bit Kevin. My code just gets more complicated, I also had to change...

Code:
if (-e "$path$no_ext_dump/$_") {
                    $_ = $_ . $underslash . $time_date_stamp;
               }

to...

Code:
if (-e "$path$no_ext_dump/$_") {
                    @split_string = split(//, $_);
                    if ($split_string[-1] eq ".") { 
                         $_ = join ("", (chop (@split_string));
                         $last_fullstop = ".";
                    }
                    else {
                         $last_fullstop = "";
                    }
                    $_ = $_ . $underslash . $time_date_stamp . $last_fullstop;
               }

This is because if the file with no exension already exists, before if the file had a . at the end then the new name was messed up...

BEFORE:
i.e. if the file was called "hello."
The new name of $_ would be something like...
"hello._020257141007"

NOW:
The new name of $_ would be something like...
"hello_020257141007."

(replaces the . onto the end)

Chris
 
in my code above, this line:

SUSPECT is for file extensions with none word characters in them.

should be:

SUSPECT is for file extensions with non-word characters in them.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Kevin, I have just seen your code. Thank you very much for taking the time to write it. Ill have a read in a second. I haven't tested yet, but I think I have accomplished every aspect of the task now, but your code seems much more efficient, so ill take a look. Thank you for the link to the Markup Language converter. So here is my version of the final code (UNTESTED), for the final time hehe.

Code:
[ol]
[li][gray][i]#############################################################################################[/i][/gray][/li]
[li][gray][i]## Tek-tips.com Topic Response                                                             ##[/i][/gray][/li]
[li][gray][i]## [URL unfurl="true"]http://tek-tips.com/viewthread.cfm?qid=1416792&page=1[/URL]                                   ##[/i][/gray][/li]
[li][gray][i]##                                                                                         ##[/i][/gray][/li]
[li][gray][i]## - Sort files with different extensions into corresponding directories.                  ##[/i][/gray][/li]
[li][gray][i]## - The corresponding directories are children of the files folder.                       ##[/i][/gray][/li]
[li][gray][i]## - If a file has no extension (i.e. file OR file.) then place into the No_Ext directory. ##[/i][/gray][/li]
[li][gray][i]## - Create the extension directories automatically, unless one already exists.            ##[/i][/gray][/li]
[li][gray][i]## - If a file name already exists, then rename it with a unique new name.                 ##[/i][/gray][/li]
[li][gray][i]#############################################################################################[/i][/gray][/li]
[li][/li]
[li][gray][i]###############[/i][/gray][/li]
[li][gray][i]#! /usr/bin/perl[/i][/gray][/li]
[li][url=http://perldoc.perl.org/functions/use.html][black][b]use[/b][/black][/url] [green]strict[/green][red];[/red][/li]
[li][black][b]use[/b][/black] [green]CGI[/green] [red]'[/red][purple]:standard[/purple][red]'[/red][red];[/red][/li]
[li][gray][i]###############[/i][/gray][/li]
[li][/li]
[li][gray][i]###############[/i][/gray][/li]
[li][gray][i]##### DECLARE VARIABLES[/i][/gray][/li]
[li][url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [red]([/red][blue]$time_date_stamp[/blue], [blue]$path[/blue], [blue]$no_ext_dump[/blue], [blue]$fullstop[/blue], [blue]$underslash[/blue], [blue]@directory_contents[/blue], [blue]$counter[/blue], [blue]$file_name[/blue], [blue]@split_name_ext[/blue], [blue]$name[/blue], [blue]$ext[/blue], [blue]@split_string[/blue], [blue]$last_fullstop[/blue][red])[/red][red];[/red][/li]
[li][gray][i]##### GET TIME/DATE STAMP[/i][/gray][/li]
[li][black][b]my[/b][/black] [red]([/red][blue]$sec[/blue], [blue]$min[/blue], [blue]$hour[/blue], [blue]$mday[/blue], [blue]$mon[/blue], [blue]$year[/blue][red])[/red]=[url=http://perldoc.perl.org/functions/gmtime.html][black][b]gmtime[/b][/black][/url][red];[/red][/li]
[li][blue]$time_date_stamp[/blue] = [url=http://perldoc.perl.org/functions/sprintf.html][black][b]sprintf[/b][/black][/url] [red]([/red][red]'[/red][purple]%02d%02d%02d%02d%02d%02d[/purple][red]'[/red], [blue]$hour[/blue], [blue]$min[/blue], [blue]$sec[/blue], [blue]$mday[/blue], [blue]$mon[/blue], [blue]$year[/blue][red])[/red][red];[/red][/li]
[li][gray][i]##### DECLARE CONTENT TYPE[/i][/gray][/li]
[li][url=http://perldoc.perl.org/functions/print.html][black][b]print[/b][/black][/url] [red]"[/red][purple]Content-type: text/html[purple][b]\n[/b][/purple][purple][b]\n[/b][/purple][/purple][red]"[/red][red];[/red][/li]
[li][gray][i]##### INITIAL VALUES[/i][/gray][/li]
[li][blue]$path[/blue] = [red]"[/red][purple]ChrisMassey.co.uk/Perl/Scripts/CleanDirectory/Files/[/purple][red]"[/red][red];[/red][/li]
[li][blue]$no_ext_dump[/blue] = [red]"[/red][purple]No_Ext[/purple][red]"[/red][red];[/red][/li]
[li][blue]$fullstop[/blue] = [red]"[/red][purple].[/purple][red]"[/red][red];[/red][/li]
[li][blue]$underslash[/blue] = [red]"[/red][purple]_[/purple][red]"[/red][red];[/red][/li]
[li][gray][i]##### START PROCESS COUNTER ON 0[/i][/gray][/li]
[li][blue]$counter[/blue] = [fuchsia]0[/fuchsia][red];[/red][/li]
[li][gray][i]##### OPEN PATH DIRECTORY AND GET CONTENTS[/i][/gray][/li]
[li][url=http://perldoc.perl.org/functions/opendir.html][black][b]opendir[/b][/black][/url] [red]([/red]LOGDIR, [red]"[/red][purple][blue]$path[/blue][/purple][red]"[/red][red])[/red] || [url=http://perldoc.perl.org/functions/die.html][black][b]die[/b][/black][/url] [red]"[/red][purple]Cannot Open: [blue]$path[/blue][/purple][red]"[/red][red];[/red][/li]
[li][blue]@directory_contents[/blue] = [url=http://perldoc.perl.org/functions/grep.html][black][b]grep[/b][/black][/url] [red]{[/red]![red]/[/red][purple]^[purple][b]\.[/b][/purple]{1,2}$[/purple][red]/[/red][red]}[/red] [url=http://perldoc.perl.org/functions/readdir.html][black][b]readdir[/b][/black][/url] [red]([/red]LOGDIR[red])[/red][red];[/red][/li]
[li][url=http://perldoc.perl.org/functions/closedir.html][black][b]closedir[/b][/black][/url] [red]([/red]LOGDIR[red])[/red][red];[/red][/li]
[li][gray][i]###############[/i][/gray][/li]
[li][/li]
[li][gray][i]###############[/i][/gray][/li]
[li][gray][i]##### MAIN LOOP[/i][/gray][/li]
[li][olive][b]foreach[/b][/olive] [red]([/red][blue]@directory_contents[/blue][red])[/red] [red]{[/red][/li]
[li]     [gray][i]##### or if file contains . in the middle of of any 2 strings (note more than one . might be there i.e. hello.big.world.[/i][/gray][/li]
[li]     [olive][b]if[/b][/olive] [red]([/red][red]([/red][blue]$_[/blue] !~ [red]/[/red][purple][purple][b]\.[/b][/purple]$[/purple][red]/[/red][red])[/red] || [red]([/red][blue]$_[/blue] =~ [red]/[/red][purple][purple][b]\.[/b][/purple]$[/purple][red]/[/red][red])[/red] || [red]([/red][red]([/red][blue]$_[/blue] !~ [red]/[/red][purple][purple][b]\.[/b][/purple]$[/purple][red]/[/red][red])[/red] && [red]([/red][blue]$_[/blue] =~ [red]/[/red][purple][purple][b]\.[/b][/purple]+[/purple][red]/[/red][red])[/red][red])[/red] || [red]([/red][red]([/red][blue]$_[/blue] =~ [red]/[/red][purple][purple][b]\.[/b][/purple]$[/purple][red]/[/red][red])[/red] && [red]([/red][blue]$_[/blue] =~ [red]/[/red][purple][purple][b]\.[/b][/purple]+[/purple][red]/[/red][red])[/red][red])[/red][red])[/red]  [red]{[/red][/li]
[li]          [olive][b]unless[/b][/olive] [red]([/red][url=http://perldoc.perl.org/functions/-X.html][black][b]-d[/b][/black][/url] [red]"[/red][purple][blue]$path[/blue][blue]$_[/blue][/purple][red]"[/red][red])[/red] [red]{[/red][/li]
[li]               [olive][b]unless[/b][/olive] [red]([/red][url=http://perldoc.perl.org/functions/-X.html][black][b]-e[/b][/black][/url] [red]"[/red][purple][blue]$path[/blue][blue]$no_ext_dump[/blue][/purple][red]"[/red][red])[/red] [red]{[/red][/li]
[li]                    [url=http://perldoc.perl.org/functions/mkdir.html][black][b]mkdir[/b][/black][/url] [red]([/red][red]"[/red][purple][blue]$path[/blue][blue]$no_ext_dump[/blue][/purple][red]"[/red], [fuchsia]0777[/fuchsia][red])[/red] || [black][b]die[/b][/black] [red]"[/red][purple]Cannot Open: [blue]$path[/blue][blue]$no_ext_dump[/blue][/purple][red]"[/red][red];[/red][/li]
[li]               [red]}[/red][/li]
[li]               [blue]$file_name[/blue] = [blue]$_[/blue][red];[/red][/li]
[li]               [olive][b]if[/b][/olive] [red]([/red][black][b]-e[/b][/black] [red]"[/red][purple][blue]$path[/blue][blue]$no_ext_dump[/blue]/[blue]$_[/blue][/purple][red]"[/red][red])[/red] [red]{[/red][/li]
[li]                    [blue]@split_string[/blue] = [url=http://perldoc.perl.org/functions/split.html][black][b]split[/b][/black][/url][red]([/red][red]/[/red][purple][/purple][red]/[/red], [blue]$_[/blue][red])[/red][red];[/red][/li]
[li]                    [olive][b]if[/b][/olive] [red]([/red][blue]$split_string[/blue][red][[/red]-[fuchsia]1[/fuchsia][red]][/red] eq [red]"[/red][purple].[/purple][red]"[/red][red])[/red] [red]{[/red] [/li]
[li]                         [blue]$_[/blue] = [url=http://perldoc.perl.org/functions/join.html][black][b]join[/b][/black][/url] [red]([/red][red]"[/red][purple][/purple][red]"[/red], [red]([/red][url=http://perldoc.perl.org/functions/chop.html][black][b]chop[/b][/black][/url] [red]([/red][blue]@split_string[/blue][red])[/red][red])[/red][red];[/red][/li]
[li]                         [blue]$last_fullstop[/blue] = [red]"[/red][purple].[/purple][red]"[/red][red];[/red][/li]
[li]                    [red]}[/red][/li]
[li]                    [olive][b]else[/b][/olive] [red]{[/red][/li]
[li]                         [blue]$last_fullstop[/blue] = [red]"[/red][purple][/purple][red]"[/red][red];[/red][/li]
[li]                    [red]}[/red][/li]
[li]                    [blue]$_[/blue] = [blue]$_[/blue] . [blue]$underslash[/blue] . [blue]$time_date_stamp[/blue] . [blue]$last_fullstop[/blue][red];[/red][/li]
[li]               [red]}[/red][/li]
[li]               [url=http://perldoc.perl.org/functions/rename.html][black][b]rename[/b][/black][/url] [red]([/red][red]"[/red][purple][blue]$path[/blue][blue]$file_name[/blue][/purple][red]"[/red], [red]"[/red][purple][blue]$path[/blue][blue]$no_ext_dump[/blue]/[blue]$_[/blue][/purple][red]"[/red][red])[/red] || [black][b]die[/b][/black] [red]"[/red][purple]Cannot Open: [blue]$path[/blue][blue]$_[/blue] - [blue]$path[/blue][blue]$no_ext_dump[/blue]/[blue]$_[/blue][/purple][red]"[/red][red];[/red][/li]
[li]               [black][b]print[/b][/black] [red]"[/red][purple]<p>[blue]$_[/blue] has been moved to [blue]$path[/blue][blue]$no_ext_dump[/blue]/[blue]$_[/blue][/purple][red]"[/red][red];[/red][/li]
[li]               [blue]$counter[/blue]++[/li]
[li]          [red]}[/red][/li]
[li]     [red]}[/red][/li]
[li]     [olive][b]else[/b][/olive] [red]{[/red][/li]
[li]          [blue]@split_name_ext[/blue] = [black][b]split[/b][/black] [red]([/red][red]/[/red][purple][purple][b]\.[/b][/purple][/purple][red]/[/red], [blue]$_[/blue][red])[/red][red];[/red][/li]
[li]          [blue]$ext[/blue] = [blue]$split_name_ext[/blue][red][[/red]-[fuchsia]1[/fuchsia][red]][/red][red];[/red][/li]
[li]          [url=http://perldoc.perl.org/functions/pop.html][black][b]pop[/b][/black][/url] [red]([/red][blue]@split_name_ext[/blue][red])[/red][red];[/red][/li]
[li]          [blue]$name[/blue] = [black][b]join[/b][/black] [red]([/red][red]"[/red][purple].[/purple][red]"[/red], [blue]@split_name_ext[/blue][red])[/red][red];[/red][/li]
[li]          [olive][b]unless[/b][/olive] [red]([/red][black][b]-e[/b][/black] [red]"[/red][purple][blue]$path[/blue][blue]$ext[/blue][/purple][red]"[/red][red])[/red] [red]{[/red][/li]
[li]               [black][b]mkdir[/b][/black] [red]([/red][red]"[/red][purple][blue]$path[/blue][blue]$ext[/blue][/purple][red]"[/red], [fuchsia]0777[/fuchsia][red])[/red] || [black][b]die[/b][/black] [red]"[/red][purple]Cannot Open: [blue]$path[/blue][blue]$ext[/blue][/purple][red]"[/red][red];[/red][/li]
[li]          [red]}[/red][/li]
[li]     [red]}[/red][/li]
[li]     [olive][b]unless[/b][/olive] [red]([/red][black][b]-d[/b][/black] [red]"[/red][purple][blue]$path[/blue][blue]$_[/blue][/purple][red]"[/red][red])[/red] [red]{[/red][/li]
[li]          [blue]$file_name[/blue] = [blue]$_[/blue][red];[/red][/li]
[li]          [olive][b]if[/b][/olive] [red]([/red][black][b]-e[/b][/black] [red]"[/red][purple][blue]$path[/blue][blue]$ext[/blue]/[blue]$_[/blue][/purple][red]"[/red][red])[/red] [red]{[/red][/li]
[li]               [blue]$_[/blue] = [blue]$name[/blue] . [blue]$underslash[/blue] . [blue]$time_date_stamp[/blue] . [blue]$fullstop[/blue] . [blue]$ext[/blue][red];[/red][/li]
[li]          [red]}[/red][/li]
[li]          [black][b]rename[/b][/black] [red]([/red][red]"[/red][purple][blue]$path[/blue][blue]$file_name[/blue][/purple][red]"[/red], [red]"[/red][purple][blue]$path[/blue][blue]$ext[/blue]/[blue]$_[/blue][/purple][red]"[/red][red])[/red] || [black][b]die[/b][/black] [red]"[/red][purple]Cannot Open: [blue]$path[/blue][blue]$_[/blue] - [blue]$path[/blue][blue]$ext[/blue]/[blue]$_[/blue][/purple][red]"[/red][red];[/red][/li]
[li]          [black][b]print[/b][/black] [red]"[/red][purple]<p>[blue]$_[/blue] has been moved to [blue]$path[/blue][blue]$ext[/blue]/[blue]$_[/blue][/purple][red]"[/red][red];[/red][/li]
[li]          [blue]$counter[/blue]++[/li]
[li]     [red]}[/red][/li]
[li][red]}[/red][/li]
[li][gray][i]##### MAIN LOOP ENDED[/i][/gray][/li]
[li][gray][i]###############[/i][/gray][/li]
[li][/li]
[li][gray][i]###############[/i][/gray][/li]
[li][gray][i]##### FINAL PRINT STATEMENT[/i][/gray][/li]
[li][black][b]print[/b][/black] [red]"[/red][purple]<p>[blue]$counter[/blue] files have been sorted[/purple][red]"[/red][red];[/red][/li]
[li][gray][i]###############[/i][/gray][/li]
[/ol]
[tt]------------------------------------------------------------
Pragmas (perl 5.8.8) used :
[ul]
[li]strict - Perl pragma to restrict unsafe constructs[/li]
[/ul]
Core (perl 5.8.8) Modules used :
[ul]
[li]CGI - Simple Common Gateway Interface Class[/li]
[/ul]
[/tt]
[/code]

Chris
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top