-4

The problem for which the perl code is to be developed is as follow:

There is a root directory that contains several directory in it. Each subdirectory has in turn a text file in it.

We need to go into each directory of the root directory and first rename the file inside that directory. Then we will need to get back, or one directory up, and replace the directory name with the same name as the text file it contains.

Steps:

  1. open each directory
  2. rename the text file in the directory opened
  3. go up one level and rename the directory itself with the same name as the text file it contains
  4. move to the next directory in the root directory
tchrist
  • 74,913
  • 28
  • 118
  • 169
  • 1
    tel me when your operating in loop will u specify same name to all the text files? what will be your new name? – run Dec 26 '11 at 06:38

3 Answers3

2

You can use the File::Find module, it traverses the directory tree recursively.The finddepth() function in the module can be used for this purpose, it does postorder traversal working from the bottom of the directory tree up.

use File::Find;
my $DirName = 'path_of_dir' ;

sub rename_subdir
{
    #The path of the file/dir being visited.
    my $orignm = $File::Find::name;
    my $newnm = $orignm . '_rename';
    print "Renaming $orignm to $newnm\n";
    rename ($orignm, $newnm);
}

#For each file and sub directory in $Dirname, 'finddepth' calls
#the 'rename_subdir' subroutine recursively.
finddepth (\&rename_subdir, $DirName);
Brad Gilbert
  • 32,263
  • 9
  • 73
  • 122
Shalini
  • 455
  • 1
  • 3
  • 5
0

Hi i am trying an overview of your idea

#!/usr/bin/perl
use strict;
use File::Find;
use Data::Dumper;
use File::Basename;
my $path = 'your root directory';
my @instance_list;
find (sub { my $str = $_;
        if($str =~ m/.txt$/g) {                             
            push @instance_list, $File::Find::name if (-e $File::Find::name); 
        } 
      }, $path);
print Dumper(@instance_list);




for my $instance (@instance_list) {
  my $newname = 'newEntry';
  my $filename = basename( $instance );
  #rename the file 1st,
  my $newFileName = dirname( $instance ) .'/'. $filename.$newname.'.txt'
;

  rename($instance, $newFileName) or die $!;
  #rename the directory
  my $newDirName = dirname(dirname( $instance ) ).'/'. $newname;

   rename(dirname($instance), $newDirName) or die $!;

}
run
  • 1,142
  • 7
  • 13
  • What the devil is `"\/"` all about, eh? – tchrist Dec 28 '11 at 13:56
  • alrit.. `"\/"` appends `/` to directory. when u construct absolute file name we need to add `'/'` to directory followed by file name for Example:`dirname( $instance )` returns `/xyz/abc` and filename will be `file.txt` then complete file will be `/xyz/abc/file.txt` if u don't add `/ it will be `/xyz/abcfile.txt` which is incorrect – run Dec 29 '11 at 04:22
  • You should not escape the slash, and you should not quote the variables the way you are doing it. – tchrist Dec 29 '11 at 05:20
0

You have not mentioned how you store the file names that will be used for renaming, so I'll assume it's a generic type of change, e.g. "file_x" -> "file_x_foo". You'll have to define that yourself.

This script will try to rename all the files in the directory, assuming the only regular file in the directory is the target file. If you have more files in the directory, you will need to supply a means of identifying that file.

The script takes an optional argument which is the root dir.

This is sample code, untested, but it should work.

use strict;
use warnings;
use autodie;
use File::Copy;

my $rootdir = shift || "/rootdir";
opendir my $dh, $rootdir;
chdir $rootdir;
my @dirlist = grep -d, readdir $dh;   
for my $dir (@dirlist) {
    next if $dir =~ /^\.\.?$/;
    chdir $dir;
    for my $org (grep -f, glob "*.txt") { # identify target file
        my $new = $org;
        $new .= "_foo";   # change file name, edit here!
        move $org, $new;
    }
    chdir "..";
    move $dir, $new;
}
TLP
  • 61,960
  • 8
  • 84
  • 140