Do you always have a single dot, and the number should go before that?
#!/usr/bin/perl
use strict;
use warnings;
my ($file, $max) = @ARGV;
my ($base, $ext) = split (/\./, $file);
for my $f (reverse <$base.*.$ext>) {
next unless ($f =~ /\.([0-9]{4})\./);
my $i = $1; # grab number we just matched into $i
if ($i >= $max) {
unlink $f or warn "$0: Could not remove $f: $!\n";
next;
}
# else
my $n = sprintf "%s.%04i.%s", $base, $i+1, $ext;
rename $f, $n or warn "$0: Could not rename $f to $n: $!\n";
}
rename $file, "$base.0001.$ext"
or warn "$0: Could not rename $file to $base.0001.$ext: $!\n";
This is as untested as it gets. I tried a shell script first but it got really ugly. Still, hope this helps (even perhaps a little bit).
I'm trying to figure out how to eliminate the uninitialized value errors in my perl code.
When doing the file split:
# Split Filename From Extention
my ($base, $ext) = split (/\./, $argFileName);
# Check For File Extension
$HaveExt = ( ( length $ext ) < 1 ? "Y" : "N" );
I get the following error:
"Use of uninitialized value in length at test.pl line 22.
For some items I may have 2 files that have the same name one with an extention and one without so I'm checking for the extention and using that later to filter the files.
I've tried a bunch of ways to get around this but I always get some form of uninitialized value error.
How can I intialize an uninitialized value?
I've even tried:
Now I'm just wondering if using "warn" is the best way to display the output to the command line? Some people here will want to see it and others won't.
I know that there is some way of re-directing the "warn"/"die" to an error log in unix, but I can't remember the syntax for it.
As per the forums rules:
Here's the code that I finished with; we'll be adding other functionality at a later time, but here it is as it stands:
#!/usr/bin/perl
use strict;
use warnings;
# Get The Argument List
my ($argFileName, $argMaxCount) = @ARGV;
# End Run If We Don't Have At Least 2 Arguments
die " - Usage : $0 <FileName> <ArchiveCount>\n" if $#ARGV < 1;
# Check For Valid Arguments
die " - $0: FileName: $argFileName does NOT exist\n" unless ( -e $argFileName );
die " - $0: ArchiveCount: $argMaxCount is less than 1\n" if ( $argMaxCount < 1 );
# Split Filename From Extention
my ($base, $ext) = split (/\./, $argFileName);
# Check For File Extension And Add "."
$ext = ( ( defined $ext ) ? ( "." . $ext ) : "" );
# Rename The Files
&myRename;
# Rename The Subfile Dictionaries As Well
if ( $ext eq ".sf" ) {
warn "\n - Processing Subfile Dictionaries:\n\n";
$ext = ".sfd";
&myRename;
}
# End Processing
exit;
sub myRename
{
# Get File List In Reverse Order
for my $curFile ( reverse <$base*$ext> ) {
# Skip Non-Matching Extentions
my ($curBase, $curExt) = split (/\./, $curFile);
$curExt = ( ( defined $curExt ) ? ( "." . $curExt ) : "" );
next unless $ext eq $curExt;
# Skip Non-Version File Names
next unless ( $curFile =~ /$base\_([0-9]{4})$ext/ );
# Save This Version Number
my $fileVersionNum = $1; # Grab Number We Just Matched Into $fileVersionNum
# Purge All Matching File Versions >= The Max Counter
if ( $fileVersionNum >= $argMaxCount ) {
warn " - Removing - $curFile\n";
unlink $curFile or warn " - $0: Could not remove $curFile: $!\n";
next;
};
# else
my $newFile = ( sprintf "%s_%04i%s", $base, $fileVersionNum+1, $ext );
warn " - Renaming - $curFile -> $newFile\n";
rename $curFile, $newFile or warn " - $0: Could not rename $curFile to $newFile: $!\n";
};
my $oldFile = ( sprintf "%s%s", $base, $ext );
my $newFile = ( sprintf "%s_%04i%s", $base, 1, $ext );
warn " - Renaming - $oldFile -> $newFile\n";
rename ( $oldFile, $newFile ) or warn " - $0: Could not rename $oldFile to $newFile: $!\n";
};
command 2>/dev/null if you don't want to see the error output from command
Might be a useful addition to add a -q option if your users are too young to know where to look for the ">" key. Also it's good to be able to tweak down the verbosity from routine warnings but still notice if there are fatal errors.
Actually, looking at your "warnings", I would make them conditional on a -v (verbose) switch instead. They're just diagnostics and if the tool is used even semi-routinely, users will not be reading that output anyway (even when things went wrong).
I would keep the $ext (and $curExt etc) without the dot, and add it when it's needed, rather than vice versa. I think it would simplify the code.
As another minor design nit, I would make myRename require the extension as a parameter, so you don't mess with global variables within and outside the function. It doesn't really matter here, just basic code hygiene.
I've tried adding a path to my file lookup but I keep getting a "readline() on unopened filehandle" on my for line:
my $ArcPathLookup = $argArcPath . $base . "*" . $ext;
warn "Lookup: $ArcPathLookup\n";
for my $curFile ( reverse <$ArcPathLookup> ) {
...
}
I get the following results:
/devuser/sjohnson # perl arcpathsave.pl edifile 5 "/devuser/sjohnson/save"
Lookup: /devuser/sjohnson/save/edifile*
readline() on unopened filehandle at arcpathsave.pl line 64.
Sorry it's probably something simple but I've looked arounds for a few hours and haven't found much, looked at the readline() and glob() but still not really understanding where and when you can add /path/filename.ext.
What we're trying to do is allow for archives to be placed in a different directory (optional arg)
We may also be using unix variables instead of a string on the command line.
Without the full code it's hard to figure out what's on line 64. The warning basically means you are trying to read a line (probably with <HANDLE>) where the HANDLE was not opened (or even defined) yet.
if I leave the path arg blank it works, but when the path is added I get the readline error.
While looking around I found this in a perl doc:
opendir(DIR, $dirname) or die "can't opendir $dirname: $!";
while (defined($file = readdir(DIR))) {
# do something with "$dirname/$file"
}
closedir(DIR);
If I am understanding this correctly:
it opens the dir
the while processes the files within the dir
then it closes it
I'm thinking that I can use this to rework the code to include an optional path arg. but I'll probably need to write 2 subs, one for the path arg and one for no path arg.
It's going to be messy but that's all I can think of right now...