finddata has asked for the wisdom of the Perl Monks concerning the following question:

The following code will rename the directories and sub directories names as per the text file (i.e mapfile.txt) mapfile.txt:
PROJECT:DCMS_DEMO:prj1 BLOCK:de_top:blk1 BLOCK:new_block2:blk2 BLOCK:test:blk3 CHECKLIST:Block_DV:checklist1 CHECKLIST:Block_Physical_design_checklist:checklist2 CHECKLIST:CAD_checklist:checklist3 CHECKLIST:DFT:checklist4
Code which i used to rename folders and sub folders as per text file:
##READ THE TEXT FILE AND RENAME THE DIRECTORIES #### my $dir_map = read_map($mapfile); my $top_dir=$output_dir; rename_dirs( $top_dir, $dir_map ); sub rename_dirs { my ( $top_dir, $dir_map ) = @_; opendir (my $dh, $top_dir) or die "Can't open $top_dir: $!"; my $save_dir = getcwd(); chdir $top_dir; while (my $dir = readdir $dh) { #print $dir,"\n"; next if ($dir eq '.') or ($dir eq '..'); if ( exists $dir_map->{$dir} ) { my $new_name = $dir_map->{$dir}; File::Copy::move( $dir, $new_name ) or die "Could not rename '$dir' as '$new_name': $!"; $dir = $new_name; } rename_dirs( $dir, $dir_map ) if -d $dir; } chdir $save_dir; } ##SUB ROUTINE TO READ THE TEXT FILE FROM COMMAND LINE ARGUMENTS## sub read_map { my ( $fn ) = @_; my %dir_map; open( my $fh, '<', $fn ) or die "Could not open file '$fn': $!"; while( my $line = <$fh> ) { chomp $line; my @fields = split /:/, $line; if ( @fields == 3 ) { $dir_map{$fields[2]} = $fields[1]; } } close $fh; return \%dir_map; }
My output obtained from above code:
DCMS_DEMO |-- DCMS_DEMO.config |-- DCMS_DEMO.html |-- de_top | |-- Block_DV | | |-- Block_DV.config | | |-- Block_DV.html | | |-- rev1 | | | |-- rev1.config | | | `-- rev1.html | | `-- rev2 | | |-- rev2.config | | `-- rev2.html | |-- CAD_checklist | | |-- CAD_checklist.config | | |-- CAD_checklist.html | | |-- rev1 | | | |-- rev1.config | | | `-- rev1.html
My query explanation: Likewise i should do for all .config file contents inside the file.And i should not consider the last level directory structure for doing the same process?(i.e rev.*) cat DCMS_DEMO.config
blk3 : 0% : 0% blk1 : 0.68% : 0.99% blk2 : 0.00% : 0.00% OVERALL_STATUS=0.23% PARTIAL_STATUS=0.33%
Expected output:
test : 0% : 0% de_top : 0.68% : 0.99% new_block2 : 0.00% : 0.00% OVERALL_STATUS=0.23% PARTIAL_STATUS=0.33%
  • Comment on How to match the file and rename the contents in the .config files of directories and subdirectories using perl?
  • Select or Download Code

Replies are listed 'Best First'.
Re: How to match the file and rename the contents in the .config files of directories and subdirectories using perl?
by Marshall (Canon) on Mar 12, 2017 at 19:48 UTC
    I am not sure what question you are asking?

    Your code looks like it should work, but I didn't test it myself. If I were doing this, I would use File::Find to do the recursion instead of implementing it myself. There is also an option of going "bottom up" using finddepth() which could also be considered. This would process all the plain files first (like your .config files) and then process the directory name that those files were in after processing that directories contents.

    It appears to me that you have a translation table hash to provide the rules to translate blk3->test and blk1->de_top, etc in the config file (your example of DCMS_DEMO.config). Are you asking how to write that code? This task appears to be straightforward although I would highly recommend making a backup copy of the original config file as a part of the editing process so that you don't loose information in the event of a crash (which might not have anything to do with your program - stuff happens).

    It looks to me like you understand the basics. Where are you stuck?

      The above code works for matching and renaming the directories.Now i like to do same process for all .config files inside those directories.And another thing it should be done before the last level of the tree(i.e we should omit the file name which ever starts with rev.config from the last level of the directory)
      Things which i really want to deliver you is that as follows:
      1.I have the match file .(from that text file i had matched the word a +nd renamed the names of the directories). 2.After directories matches are done i need to do same process fo all +.config files inside those sub directories and directories. 3.But the point 2 should done without affecting all rev.config files f +rom the same directories and sub directories.
        I see that have have started a number of threads related to this project and that you have written more code since this post.

        I think poj nailed your current problem at Re^5: Unable to rename the contents of the file using perl?. You have to de-reference $string which is a reference a string. In a situation like your code:

        sub write_new_file { my ( $fn, $str ) = @_;
        $fn is a simple string, but $str is actually a reference to a string. I personally would use different variable names to indicate the "type", e.g.
        my ($fn, $str_ref ) = @_; # or $ref_str, $r_str or other possibilities
        This sort of thing can help remind you that to print the contents of $string, you need print $$string instead of just print $string

        If you want process files than end in ".config", but not those like "XXX_rev4.config", a simple way would be to just put

        next if $name =~ /rev\d+\.config$/; if ($name =~ /\.config$/) {blah..blah}