tags:

views:

270

answers:

4

Possible duplicate: http://stackoverflow.com/questions/2548835/renaming-and-moving-files-in-bash-or-perl/2548919#2548919

I'm kinda newbie to perl and looking for a script that will handle file moving.

#!/usr/bin/perl -w
$filename = 'DUMBFILE';
$destination = '/some/location/';
if (-e $destination + $filename) {
  print "File Exists ! Renaming ..";
  move ('/tmp/' + $filename, $destination + $filename + '.1');
} else {
  move ('/tmp/' + $filename, $destination + $filename);
}

I'm able to rename it to 1, but i want to be renamed incrementally, like if file.1 exists, rename to .2, and .3 if .2 exists.

EDIT : and keep the extension the same; like file.exe becomes file.exe.1, file.exe.2 etc.

+4  A: 

You need to concatenation . instead of +:

if (-e $destination . $filename) {

Or even better. You can use File::Spec module:

use File::Spec;
...
if (-e File::Spec->join($destination, $filename)) {

And please use strict;

To move file you can use File::Copy module:

use File::Copy;
...
move($from, $to);
Ivan Nevostruev
This still doesn't address the core part of the question - the incremental counter appended to the name.
Jefromi
+4  A: 

Probably what you want to do is something like:

use File::Copy;

sub construct_filename {
    my ($dir, $name, $counter) = @_;
    if ($name =~ /^(.*)\.(.*)$/) {
        return "$dir/$1.$counter.$2";
    } else {
        return "$dir/$name.$counter";
    }
}

if (-e "$destination$filename") {
    $counter = 1;
    while (-e construct_filename($destination,$filename,$counter)) {
        $counter++;
    }
    move("/tmp/$filename", construct_filename($destination,$filename,$counter));
} else {
    move("/tmp/$filename", "$destination$filename");
}

Also, the string concatenation operator in perl is ., not +. What you wrote isn't going to work at all. In this case you can just use double-quoted string interpolation though, and not bother with concatenation.

And for what it's worth, an easier convention is for directories to never contain trailing slashes, and to always use them when you construct filenames (e.g. "$destination/$filename"). As others have pointed out, the most robust way to do the path-building is with File::Spec. From what I could tell, though, the part you were really looking for was how to do the incremental naming; so I've given a clear and short version of that. Upgrade to File::Spec as you see fit!

Jefromi
There's a race condition between checking for $filename.$counter and using it. This will probably never be an issue but is worth knowing about.
Josh Kelley
@Josh Kelley: Thanks, I meant to mention that but forgot by the time I was done.
Jefromi
Thanks, it's working ... but now i see that i don't want to rename the file to .1 but keep the extension instead.Like having 'file.exe' rename to 'file.1.exe' 'file.2.exe' etc ...
Disco
@Disco: You should be able to pop off the extension using `File::Basename`. If you put that together with other answers, you should have what you need: a `while` loop to keep checking for existing filenames, `File::Spec` to build names out of pieces of a path, and `.` to concatenate the extension onto the end.
Telemachus
@Telemachus: Doesn't `File::Basename` require a list of suffixes? Or can those be patterns... I forget. @Disco: I added a simple way to do that. (As always, you can reimplement using `File::Spec`; I'm just trying to keep this short) Of course, I really think you should probably be going off and giving it a shot on your own before asking us to write more for you...
Jefromi
@Jefromi: `File::Basename` takes a list of suffixes as an (optional) parameter. The items you give in that list can be strings or a regex using `qr//`. I guess my real point was that the OP should have enough to go on to try some of this on his own - as you said in your follow-up.
Telemachus
@Telemachus: Ah, thanks for that. I was remembering the standard utility, not the perl function.
Jefromi
Maybe one of you can provide me an example ? I'm really not finding out. Thanks
Disco
The one with extension preservation is in a duplicate questionhttp://stackoverflow.com/questions/2548835/renaming-and-moving-files-in-bash-or-perl/2548919#2548919
DVK
@DVK: I knew I'd seen that one - thanks for the link. @Disco: Like I said, I added a simple way to do the extension preservation into my answer. Please read that, and the duplicate linked by DVK, before you ask for more help.
Jefromi
@Jefromi - yeah, it was a funny timing for thsoe 2 Qs :)Just wish I saw this one sooner and spared everyone the trouble of writing the answers by right away pointing out dupeness.
DVK
+1  A: 
#!/usr/bin/perl -w
$filename = 'DUMBFILE';
$destination = '/some/location/';
$filepath=$destination.$filename;
if (-e $filepath) {
  print "File Exists ! Renaming ..";
  $counter++;
  rename('/tmp/'.$filename.$filepath.$counter);
} else {
  move ('/tmp/'.$filename.$filepath);
}
ghostdog74
+1  A: 
#!/usr/bin/perl
use strict;
use warnings;

use File::Spec::Functions qw'catfile';
use File::Copy qw'move';
use autodie    qw'move';

my $filename    = 'DUMBFILE';
my $origin      = '/tmp';
my $destination = '/some/location';

my $path = catfile $destination, $filename;
{
  my $counter;
  while( -e $path ){
    $counter++;
    $path = catfile $destination, "$filename.$counter";
  }
}

move( catfile( $origin, $filename ), $path );
Brad Gilbert
Same with extension keeping ? (see my other comment)
Disco
@Disco, perhaps you should edit your question.
Brad Gilbert
http://stackoverflow.com/questions/2548835/renaming-and-moving-files-in-bash-or-perl/2548919#2548919 has the answer with extension keeping
DVK