So I have a program that I want to clean some text files. The program a开发者_如何转开发sks 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?
I'm not certain of what do you want. So, I made some assumptions:
- When you say clean the text file, you meant delete the text file
- The names of the files you want to write into are formed by a pattern.
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 $_;
}
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:
- using "@dir" as the array of files was a bit misleading
- the folder name needs to be prepended to the file name to get the right file
- it might be convenient to use
grep
to throw out unwanted files and subfolders, especially ".."
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.
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.
精彩评论