Question

I am trying to prefix a string (reference_) to the names of all the *.bmp files in all the directories as well sub-directories. The first time we run the silk script, it will create directories as well subdirectories, and under each subdirectory it will store each mobile application's sceenshot with .bmp extension.

When I run the automated silkscript for second time it will again create the *.bmp files in all the subdirectories. Before running the script for second time I want to prefix all the *.bmp with a string reference_.

For example first_screen.bmp to reference_first_screen.bmp, I have the directory structure as below:

C:\Image_Repository\BG_Images\second
...
C:\Image_Repository\BG_Images\sixth

having first_screen.bmp and first_screen.bmp files etc...

Could any one help me out?

How can I prefix all the image file names with reference_ string?

When I run the script for second time, the Perl script in silk will take both the images from the sub-directory and compare them both pixel by pixel. I am trying with code below. Could you please guide me how can I proceed to complete this task.

#!/usr/bin/perl -w
&one;

&two;

sub one {

    use Cwd;

    my $dir ="C:\\Image_Repository";
    #print "$dir\n";
    opendir(DIR,"+<$dir") or "die $!\n";
    my @dir = readdir DIR;
    #$lines=@dir;
    delete $dir[-1];
    print "$lines\n";
    foreach my $item (@dir)
    {
        print "$item\n";
    }
    closedir DIR;
}

sub two {

    use Cwd;

    my $dir1 ="C:\\Image_Repository\\BG_Images";
    #print "$dir1\n";
    opendir(D,"+<$dir1") or "die $!\n";
    my @dire = readdir D;
    #$lines=@dire;
    delete $dire[-1];
    #print "$lines\n";
    foreach my $item (@dire)
    {
        #print "$item\n";
        $dir2="C:\\Image_Repository\\BG_Images\\$item";
        print $dir2;
        opendir(D1,"+<$dir2") or die " $!\n";
        my @files=readdir D1;
        #print "@files\n";  
        foreach $one (@files)
        {
            $one="reference_".$one;
            print "$one\n";
            #rename $one,Reference_.$one;
        }
    }
    closedir DIR;
}

I tried open call with '+<' mode but I am getting compilation error for the read and write mode. When I am running this code, it shows the files in BG_images folder with prefixed string but actually it's not updating the files in the sub-directories.

Was it helpful?

Solution

You don't open a directory for writing. Just use opendir without the mode parts of the string:

opendir my($dir), $dirname or die "Could not open $dirname: $!";

However, you don't need that. You can use File::Find to make the list of files you need.

#!/usr/bin/perl
use strict;
use warnings;

use File::Basename;
use File::Find;
use File::Find::Closures qw(find_regular_files);
use File::Spec::Functions qw(catfile);


my( $wanted, $reporter ) = find_regular_files;
find( $wanted, $ARGV[0] );


my $prefix = 'recursive_';


foreach my $file ( $reporter->() )
    {
    my $basename = basename( $file );

    if( index( $basename, $prefix ) == 0 )
        {
        print STDERR "$file already has '$prefix'! Skipping.\n";
        next;
        }

    my $new_path = catfile( 
        dirname(  $file ), 
        "recursive_$basename"
        );

    unless( rename $file, $new_path )
        {
        print STDERR "Could not rename $file: $!\n";
        next;
        }

    print $file, "\n";  
    }

OTHER TIPS

You should probably check out the File::Find module for this - it will make recursing up and down the directory tree simpler.

You should probably be scanning the file names and modifying those that don't start with reference_ so that they do. That may require splitting the file name up into a directory name and a file name and then prefixing the file name part with reference_. That's done with the File::Basename module.

At some point, you need to decide what happens when you run the script the third time. Do the files that already start with reference_ get overwritten, or do the unprefixed files get overwritten, or what?

The reason the files are not being renamed is that the rename operation is commented out. Remember to add use strict; at the top of your script (as well as the -w option which you did use).

If you get a list of files in an array @files (and the names are base names, so you don't have to fiddle with File::Basename), then the loop might look like:

   foreach my $one (@files)
   {
        my $new = "reference_$one";
        print "$one --> $new\n";
        rename $one, $new or die "failed to rename $one to $new ($!)";
   }

With the aid of find utility from coreutils for Windows:

$ find -iname "*.bmp" | perl -wlne"chomp; ($prefix, $basename) = split(m~\/([^/]+)$~, $_); rename($_, join(q(/), ($prefix, q(reference_).$basename))) or warn qq(failed to rename '$_': $!)"
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top