Reputation: 113
So I have a program that I want to clean some text files. The program asks for the user to enter the full pathway of a directory containing these text files. From there I want to read the files in the directory, print them to a new file (that is specified by the user), and then clean them in the way I need. I have already written the script to clean the text files.
I ask the user for the directory to use:
chomp ($user_supplied_directory = <STDIN>);
opendir (DIR, $user_supplied_directory);
Then I need to read the directory.
my @dir = readdir DIR;
foreach (@dir) {
Now I am lost.
Any help please?
Upvotes: 2
Views: 7975
Reputation: 1482
You can do the following, which allows the user to supply their own directory or, if no directory is specified by the user, it defaults to a designated location.
The example shows the use of opendir
, readdir
, stores all files in the directory in the @files
array, and only files that end with '.txt' in the @keys
array. The while loop ensures that the full path to the files are stored in the arrays.
This assumes that your "text files" end with the ".txt" suffix. I hope that helps, as I'm not quite sure what's meant by "cleaning the files".
use feature ':5.24';
use File::Copy;
my $dir = shift || "/some/default/directory";
opendir(my $dh, $dir) || die "Can't open $dir: $!";
while ( readdir $dh ) {
push( @files, "$dir/$_");
}
# store ".txt" files in new array
foreach $file ( @files ) {
push( @keys, $file ) if $file =~ /(\S+\.txt\z)/g;
}
# Move files to new location, even if it's across different devices
for ( @keys ) {
move $_, "/some/other/directory/"; || die "Couldn't move files: $!\n";
}
See the perldoc of File::Copy for more info.
Upvotes: 0
Reputation: 80384
I wrote something today that used readdir
. Maybe you can learn something from it. This is just a part of a (somewhat) larger program:
our @Perls = ();
{
my $perl_rx = qr { ^ perl [\d.] + $ }x;
for my $dir (split(/:/, $ENV{PATH})) {
### scanning: $dir
my $relative = ($dir =~ m{^/});
my $dirpath = $relative ? $dir : "$cwd/$dir";
unless (chdir($dirpath)) {
warn "can't cd to $dirpath: $!\n";
next;
}
opendir(my $dot, ".") || next;
while ($_ = readdir($dot)) {
next unless /$perl_rx/o;
### considering: $_
next unless -f;
next unless -x _;
### saving: $_
push @Perls, "$dir/$_";
}
}
}
{
my $two_dots = qr{ [.] .* [.] }x;
if (grep /$two_dots/, @Perls) {
@Perls = grep /$two_dots/, @Perls;
}
}
{
my (%seen, $dev, $ino);
@Perls = grep {
($dev, $ino) = stat $_;
! $seen{$dev, $ino}++;
} @Perls;
}
The crux is push(@Perls, "$dir/$_")
: filenames read by readdir
are basenames only; they are not full pathnames.
Upvotes: 1
Reputation: 1287
I would suggest that you switch to File::Find. It can be a bit of a challenge in the beginning but it is powerful and cross-platform.
But, to answer your question, try something like:
my @files = readdir DIR;
foreach $file (@files) {
foo($user_supplied_directory/$file);
}
where "foo" is whatever you need to do to the files. A few notes might help:
grep
to throw out unwanted files and subfolders, especially ".." Upvotes: 2
Reputation: 6442
I'm not certain of what do you want. So, I made some assumptions:
So, if I'm right, try something like this:
chomp ($user_supplied_directory = <STDIN>);
opendir (DIR, $user_supplied_directory);
my @dir = readdir DIR;
foreach (@dir) {
next if (($_ eq '.') || ($_ eq '..'));
# Reads the content of the original file
open FILE, $_;
$contents = <FILE>;
close FILE;
# Here you supply the new filename
$new_filename = $_ . ".new";
# Writes the content to the new file
open FILE, '>'.$new_filename;
print FILE $content;
close FILE;
# Deletes the old file
unlink $_;
}
Upvotes: 2