rename the specific file with current time stamp using perl script for windows - perl

I am using the below script to rename but it is renaming the all file end with STA.I need to rename the file that starts with KRAT or TRAT.
#!/usr/local/bin/perl
use strict;
use warnings;
use File::Copy;
my $directory = 'C:\Users\Desktop';
chdir($directory) or die "Can't chdir to $directory $!";
opendir(DIR, $directory) || die "Couldn't opendir: $!\n";
my #files = grep { $_ ne '.' && $_ ne '..' } readdir DIR;
foreach(#files) {
print $_,"\n";
my $newName = $_;
$newName =~ s/STA$/t00/g;
print "RENAMING: $_ -> $newName \n";
rename($_, $newName);
}

Change the line
$newName =~ s/STA$/t00/g;
to
$newName =~ s/^KRAT|^TRAT/t00/;
or more succint.
#!/usr/local/bin/perl
use strict;
use warnings;
my $directory = '<DIR>';
chdir($directory) or die "Can't chdir to $directory $!";
opendir(DIR, $directory) || die "Couldn't opendir: $!\n";
rename_file($_) for grep { $_ ne '.' && $_ ne '..' && /^KRAT|^TRAT/} readdir DIR
closedir(DIR);
sub rename_file {
my $name = shift;
$name =~ s/^KRAT|^TRAT/t00/;
rename($_, $name);
}

Related

List file in directory and store in array. That array can be access outside the loop

I want to list the files in the folder and want to store in array. How can I make the array can be access outside the loop? I need that array to be outside as need to use it outside the array
This is the code:
use strict;
use warnings;
my $dirname = "../../../experiment/";
my $filelist;
my #file;
open ( OUTFILE, ">file1.txt" );
opendir ( DIR, $dirname ) || die "Error in opening dir $dirname\n";
while ( $filelist = readdir (DIR) ) {
next if ( $filelist =~ m/\.svh$/ );
next if ( $filelist =~ m/\.sv$/ );
next if ( $filelist =~ m/\.list$/ );
push #fileInDir, $_;
}
closedir(DIR);
print OUTFILE " ", #fileInDir;
close OUTFILE;
The error message is
Use of uninitialized value in print at file.pl line 49.
You're pushing the unitialized variable $_ onto the array rather than $filelist, which is misleadingly named (it's just one file name).
You can use:
use strict;
use warnings;
my $dirname = "../../../experiment/";
my $fname = "file1.txt";
my #files;
open my $out_fh, ">", $fname or die "Error in opening file $fname: $!";
opendir my $dir, $dirname or die "Error in opening dir $dirname: $!";
while (my $file = readdir($dir)) {
next if ($file =~ m/\.svh$/);
next if ($file =~ m/\.sv$/);
next if ($file =~ m/\.list$/);
push #files, $file;
}
print $out_fh join "\n", #files;
closedir $dir;
close $out_fh;

How to get files names with specific extension from a folder in perl

Currently in a perl script I am using the glob function to get a list of files with specific extensions.
my #filearray = glob("$DIR/*.abc $DIR/*.llc");
Is there any alternative to glob, to get the list of files with specific extension from a folder? If so please provide me some example? Thank you
Yes, there are much more complicated ways, like opendir, readdir and a regex filter. They will also give you the hidden files (or dotfiles):
opendir DIR, $DIR or die $!;
my #filearray = grep { /\.(abc|llc)$/ } readdir DIR;
closedir DIR;
#Using:
opendir(DIR, $dir) || die "$!";
my #files = grep(/\.[abc|lic]*$/, readdir(DIR));
closedir(DIR);
#Reference: CPAN
use Path::Class; # Exports dir() by default
my $dir = dir('foo', 'bar'); # Path::Class::Dir object
my $dir = Path::Class::Dir->new('foo', 'bar'); # Same thing
my $file = $dir->file('file.txt'); # A file in this directory
my $handle = $dir->open;
while (my $file = $handle->read)
{
$file = $dir->file($file); # Turn into Path::Class::File object
...
}
#Reference: Refered: http://accad.osu.edu/~mlewis/Class/Perl/perl.html#cd
# search for a file in all subdirectories
#!/usr/local/bin/perl
if ($#ARGV != 0) {
print "usage: findfile filename\n";
exit;
}
$filename = $ARGV[0];
# look in current directory
$dir = getcwd();
chop($dir);
&searchDirectory($dir);
sub searchDirectory
{
local($dir);
local(#lines);
local($line);
local($file);
local($subdir);
$dir = $_[0];
# check for permission
if(-x $dir)
{
# search this directory
#lines = `cd $dir; ls -l | grep $filename`;
foreach $line (#lines)
{
$line =~ /\s+(\S+)$/;
$file = $1;
print "Found $file in $dir\n";
}
# search any sub directories
#lines = `cd $dir; ls -l`;
foreach $line (#lines)
{
if($line =~ /^d/)
{
$line =~ /\s+(\S+)$/;
$subdir = $dir."/".$1;
&searchDirectory($subdir);
}
}
}
}
Please try another one:
use Cwd;
use File::Find;
my $dir = getcwd();
my #abclicfiles;
find(\&wanted, $dir);
sub wanted
{
push(#abclicfiles, $File::Find::name) if($File::Find::name=~m/\.(abc|lic)$/i);
}
print join "\n", #abclicfiles;
This the directory which is getting from user:
print "Please enter the directory: ";
my $dir = <STDIN>;
chomp($dir);
opendir(DIR, $dir) || die "Couldn't able to read dir: $!";
my #files = grep(/\.(txt|lic)$/, readdir(DIR));
closedir(DIR);
print join "\n", #files;

Match and Display the directory path and its name entered by user using PERL

I want to display the path and name of the directory when the user enters the directory name using perl.
Below is the code were i am stuck
#!/usr/local/perl/bin/perl
use strict;
use warnings;
print "enter the username\n";
my $username = <STDIN>;
my $dir = '/home';
opendir(DIR, $dir) or die $!;
if($dir =~ $username){
print "Yes I got it.\n";
}
else{
print "Username not found.\n";
}
closedir(DIR);
exit 0;
opendir( $dh, $userdir ) || die "$!";
while( ($filename = readdir(DIR))){
### do you matching here with $filename
}
closedir $dh;

location of file in perl

As suggested by Chris, a user on this site. In the 1st perl script: The values are stored in the dictionary.The first script is fine.The first script runs for only one time and stores the values. It is working.
In the 2nd script:
my $processed = retrieve('processed_dirs.dat'); # $processed is a hashref
Here it is reading the "processed_durs.dat" which is in the first script. So, I am just wondering how the second script knows the location of Processed_dirs.dat here?
#!/usr/bin/perl
use strict;
use warnings;
use Storable;
# This script to be run 1 time only. Sets up 'processed' directories hash.
# After this script is run, ready to run the daily script.
my $dir = '.'; # or what ever directory the date-directories are stored in
opendir my $dh, $dir or die "Opening failed for directory $dir $!";
my #dir = grep {-d && /^\d\d-\d\d-\d\d$/ && $_ le '11-04-21'} readdir $dh;
closedir $dh or die "Unable to close $dir $!";
my %processed = map {$_ => 1} #dir;
store \%processed, 'processed_dirs.dat';
2nd Script:
#!/usr/bin/perl
use strict;
use warnings;
use File::Copy;
use Storable;
my $dir = shift or die "Provide path on command line. $!";
my $processed = retrieve('processed_dirs.dat'); # $processed is a hashref
opendir my $dh, $dir or die "Opening failed for directory $dir $!";
my #dir = grep {-d && /^\d\d-\d\d-\d\d$/ && !$processed->{$_} } readdir $dh;
closedir $dh or die "Unable to close $dir $!";
#dir or die "Found no unprocessed date directories";
my $fdir = '/some/example/path';
for my $date (#dir) {
my $dday = "$dir/$date";
my #gzfiles = glob("$dday/*tar.gz");
foreach my $zf (#gzfiles) {
next if $zf =~ /BMP/ || $zf =~ /LG/ || $zf =~ /MAP/ || $zf =~ /STR/;
print "$zf\n";
copy($zf, $fdir) or die "Unable to copy $zf to $fdir. $!";
}
$processed->{ $date } = 1;
}
store $processed, 'processed_dirs.dat';
Unless I'm missing something, the answer is: Both scripts use a file called "processed_dirs.dat", in whatever directory they are run from. So as long as both scripts are run from the same directory, they will both use the same file.

What's that best way to move through directories?

Are both of the examples below OK, or is the second one bad style?
Case 1: Stay in top directory and use catdir to access subdirectories
#!/usr/bin/env perl
use warnings; use strict;
my $dir = 'my_dir_with_subdir';
my ( $count, $dh );
use File::Spec::Functions;
$count = 0;
opendir $dh, $dir or die $!;
while ( defined( my $file = readdir $dh ) ) {
next if $file =~ /^\.{1,2}$/;
my $sub_dir = catdir $dir, $file;
if ( -d $sub_dir ) {
opendir my $dh, $sub_dir or die $!;
while ( defined( my $file = readdir $dh ) ) {
next if $file =~ /^\.{1,2}$/;
$count++;
}
closedir $dh or die $!;
}
else {
$count++;
}
}
closedir $dh or die $!;
print "$count\n";
Case 2: Change to subdirectories and restore top directory before exit
use Cwd;
my $old = cwd;
$count = 0;
opendir $dh, $dir or die $!;
chdir $dir or die $!;
while ( defined( my $file = readdir $dh ) ) {
next if $file =~ /^\.{1,2}$/;
if ( -d $file ) {
opendir my $dh, $file or die $!;
chdir $file or die $!;
while ( defined( my $file = readdir $dh ) ) {
next if $file =~ /^\.{1,2}$/;
$count++;
}
closedir $dh or die $!;
chdir $dir;
}
else {
$count++;
}
}
closedir $dh or die $!;
chdir $old or die $!;
print "$count\n";
Your question is whether you should change to the directories you are going through or stay in the top level directory.
The answer is: It depends.
For example, consider File::Find. The default behavior is to indeed change directories. However, the module also provides a no_chdir option in case that is not desirable.
In the case of your examples, File::Find is probably not appropriate because you do not want to recurse through all subdirectories but only one. Here is a File::Slurp::read_dir based variation on your script.
#!/usr/bin/perl
use strict; use warnings;
use File::Slurp;
use File::Spec::Functions qw( catfile );
my ($dir) = #ARGV;
my $contents = read_dir $dir;
my $count = 0;
for my $entry ( #$contents ) {
my $path = catfile $dir, $entry;
-f $path and ++ $count and next;
-d _ and $count += () = read_dir $path;
}
print "$count\n";
For your example, it's best to change to subdirectories, and don't bother changing back to the original directory at the end. That's because each process has its own "current directory", so the fact that your perl script is changing it's own current directory does not mean that the shell's current directory is changed; that stays unaltered.
If this was part of a larger script it would be different; my general preference then would be not to change directory, just to reduce confusion over what the current directory is at any point in the script.
Use File::Find, as you already proposed :)
It's almost always better to use a module for solved problems like this than to roll your own, unless you really want to learn about walking dirs...