rark
asked on
how recursively find and rename all files ending in .txt to .oldtxt
how do i recursively search a directory for all files ending in .txt?
then how do i rename them all to .oldtxt?
in shell
then how do i rename them all to .oldtxt?
in shell
In shell:
find /path/to/files -type f -name \*.txt -exec mv \{\} \{\}.oldtxt \;
find /path/to/files -type f -name \*.txt -exec mv \{\} \{\}.oldtxt \;
perl -MFile::Find -e 'find(sub{-f && ($o=$_)=~s/\.txt$/.oldtxt/ && rename $_,$o},"."'
This should do it in PERL
pass the initial starting directory to it like:
recursiveRename.p </home/myname/something (no trailing slash)
#!/usr/bin/perl
use strict;
my $start = $ARGV[0];
opendir (STARTDIR, $start) or die "Can't start in $start. $!";
while (my $file = readdir(STARTDIR))
{
findIt("$start");
next if ($file =~ m/^\.$|^\.\.$/);
next if (! -d "$start/$file");
findIt("$start/$file");
}
closedir(STARTDIR);
exit;
########################## ########## ########## ########## ########## ########## ####
sub findIt($)
{
my $dir = shift;
opendir (DIR, $dir) or die "Can't open $dir. $!";
while (my $file = readdir(DIR))
{
next if ($file =~ m/^\.$|^\.\.$/);
# do recursion if this file is a dir
findIt("$dir/$file") if (-d "$dir/$file");
if ($file =~ m/(.+)\.txt$/i)
{
if (rename("$dir/$file", "$dir/$1.oldtxt"))
{
print "Renamed $file to $1.oldtxt \n";
}
else
{
print "Error Renaming $file. $! \n";
}
}
}
closedir (DIR);
return;
}
pass the initial starting directory to it like:
recursiveRename.p </home/myname/something (no trailing slash)
#!/usr/bin/perl
use strict;
my $start = $ARGV[0];
opendir (STARTDIR, $start) or die "Can't start in $start. $!";
while (my $file = readdir(STARTDIR))
{
findIt("$start");
next if ($file =~ m/^\.$|^\.\.$/);
next if (! -d "$start/$file");
findIt("$start/$file");
}
closedir(STARTDIR);
exit;
##########################
sub findIt($)
{
my $dir = shift;
opendir (DIR, $dir) or die "Can't open $dir. $!";
while (my $file = readdir(DIR))
{
next if ($file =~ m/^\.$|^\.\.$/);
# do recursion if this file is a dir
findIt("$dir/$file") if (-d "$dir/$file");
if ($file =~ m/(.+)\.txt$/i)
{
if (rename("$dir/$file", "$dir/$1.oldtxt"))
{
print "Renamed $file to $1.oldtxt \n";
}
else
{
print "Error Renaming $file. $! \n";
}
}
}
closedir (DIR);
return;
}
jasonsbytes, you probably want to either localise the dir handle or the list of files so that the recursion doesn't reset the parents dirhandle.
Or just let File::Find take care of it.
Or just let File::Find take care of it.
#!/usr/bin/perl -w
use strict;
use File::Find;
use Cwd 'abs_path';
find(\&files, abs_path('.'));
sub files {
if (/\.txt$/i) {
my ($new_name) = ($File::Find::name =~ /(.+)\.txt$/i);
$new_name .= ".oldtxt";
rename($File::Find::name, $new_name) or die "Cannot rename $File::Find::name: $!";
}
}
use strict;
use File::Find;
use Cwd 'abs_path';
find(\&files, abs_path('.'));
sub files {
if (/\.txt$/i) {
my ($new_name) = ($File::Find::name =~ /(.+)\.txt$/i);
$new_name .= ".oldtxt";
rename($File::Find::name, $new_name) or die "Cannot rename $File::Find::name: $!";
}
}
thx ozo!
ASKER
perl -MFile::Find -e 'find(sub{-f && ($o=$_)=~s/\.txt$/.oldtxt/ && rename $_,$o},"."'
thank you all.
i pasted in ozo's solution. got this
syntax error at -e line 1, at EOF
Execution of -e aborted due to compilation errors.
also, how do i just find recursively all filenames "*.txt" and "*.oldtxt" so that i can verify the changes were made?
thank you
thank you all.
i pasted in ozo's solution. got this
syntax error at -e line 1, at EOF
Execution of -e aborted due to compilation errors.
also, how do i just find recursively all filenames "*.txt" and "*.oldtxt" so that i can verify the changes were made?
thank you
Windows or Unix/Linux?
ASKER
suse linux
#!/usr/bin/perl -w
use strict;
use File::Find;
use Cwd 'abs_path';
my ($renamed, $prior, $verified, $missed);
open (LOG, ">files_changed.log") or die;
print LOG "\n******************* Rename stage *******************\n";
find(\&files, abs_path('.'));
print LOG "Renamed $renamed files, found " . ($prior || 0) . " existing *.oldtxt files\n\n";
print LOG "\n******************* Verification stage *******************\n";
find(\&verify, abs_path('.'));
print LOG "Verified $verified files, found " . ($missed || 0) . " misseed *.txt files\n\n";
sub files {
if (/\.txt$/i) {
my ($new_name) = ($File::Find::name =~ /(.+)\.txt$/i);
$new_name .= ".oldtxt";
rename($File::Find::name, $new_name) or die "Cannot rename $File::Find::name: $!";
$renamed++;
print LOG "Renamed\n\t$File::Find::n ame\nto\n\ t$new_name \n\n";
} elsif (/\.oldtxt$/i) {
print LOG "Found $File::Find::name already matching *.oldtxt\n\n";
$prior++;
}
}
sub verify {
if (/\.oldtxt$/i) {
print LOG "\nFound $File::Find::name matching *.oldtxt\n\n";
$verified++;
} elsif (/\.txt$/i) {
print LOG "\nMissed $File::Find::name *.txt\n\n";
$missed;
}
}
use strict;
use File::Find;
use Cwd 'abs_path';
my ($renamed, $prior, $verified, $missed);
open (LOG, ">files_changed.log") or die;
print LOG "\n******************* Rename stage *******************\n";
find(\&files, abs_path('.'));
print LOG "Renamed $renamed files, found " . ($prior || 0) . " existing *.oldtxt files\n\n";
print LOG "\n******************* Verification stage *******************\n";
find(\&verify, abs_path('.'));
print LOG "Verified $verified files, found " . ($missed || 0) . " misseed *.txt files\n\n";
sub files {
if (/\.txt$/i) {
my ($new_name) = ($File::Find::name =~ /(.+)\.txt$/i);
$new_name .= ".oldtxt";
rename($File::Find::name, $new_name) or die "Cannot rename $File::Find::name: $!";
$renamed++;
print LOG "Renamed\n\t$File::Find::n
} elsif (/\.oldtxt$/i) {
print LOG "Found $File::Find::name already matching *.oldtxt\n\n";
$prior++;
}
}
sub verify {
if (/\.oldtxt$/i) {
print LOG "\nFound $File::Find::name matching *.oldtxt\n\n";
$verified++;
} elsif (/\.txt$/i) {
print LOG "\nMissed $File::Find::name *.txt\n\n";
$missed;
}
}
perl -MFile::Find -e 'find(sub{-f && ($o=$_)=~s/\.txt$/.oldtxt/ && rename $_,$o},".")'
ASKER CERTIFIED SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
ASKER
ozo. bravo! thank you.
i also replaced txt with TXT, oldtxt with OLDTEXT and ran it again. i assume that's fine. am i right?
i also replaced txt with TXT, oldtxt with OLDTEXT and ran it again. i assume that's fine. am i right?
ASKER
thanks to everyone else also
In Shell you do a little loop like this on the command line or you can put it into a file and run the file:
FRINK:/u/home/jminton> find . -type f |grep \.txt$ | sed "s/\.txt//" | while read file
> do
> mv $file.txt $file.oldtxt
> done
If you want it in perl, let me know -- it's a little more involved.