我尝试使用以下代码搜索.txt文件,并在将其复制到不同目录时重命名。
#!/bin/perl
use File::Basename;
@txtfiles = <*/*.txt>;
foreach my $file(@textfiles){
$dir = dirname($file);
$file = basename($file);
$file =~ s/(\d+)/$dir/; //renaming number with $dir
`mkdir -p summary` unless -d summary;
`cp $file summary`;
}
上面的代码给出了错误,说明没有要复制的文件但是每行的print语句都正确显示(重命名的文件名)
答案 0 :(得分:1)
<强> 真是没有! 强>
不要使用系统命令 - 尤其是因为您可以使用Perl命令。
`mkdir -p summary` unless -d summary;
`cp $file summary`;
使用 Perl 命令!
use File::Copy; # Standard Perl Module. USE IT!
...
mkdir 'summary' unless -d 'summary'; # No need for `-p`
copy $file, 'summary';
这是一个经过修改的脚本:
#! /usr/bin/env perl
use strict;
use warnings;
use feature qw(say);
# use File::Basename; -- No need for this in this version
use File::Copy;
# What files do you want to find?
# Do you want to find the immediate files or the
# files in the subdirectories?
my @text_files = glob('*.txt'); # Immediate files only
mkdir 'summary' if not -d 'summary'; # Make this dir before the loop
for my $file ( @text_files ) {
next unless -f $file; # Make sure this is a file you want to copy!
#
# No need for 'dirname' and 'basename' with '*.txt' glob
#
if ( not copy $file, 'summary' ) { # Check the outcome of this command.
warn qq(Could not copy file "$file" to "summary".);
}
}
如果您需要复制子目录中的文件而不是仅在直接目录中,请告诉我们。也许您可以使用make_tree
中的File::Path
或find
中的File::Find
的Perl版本。这些是所有Perl安装都具有的标准Perl模块。
我不想要当前目录。这些文件位于一个目录中,即
foo/text_v0001.txt
,foo/text_v0002.txt
,foo_au/text_v0003.txt
,foo_au/text_v0004.txt
继续....我想用目录名替换数字,例如foo/text_v0001.txt
应重命名为text_foo.txt
,foo/text_v0002.txt
应重命名为text_foo.txt
(因为在同一文件夹中我们无法使用相同的名称文件,因此我们可以添加第2部分和第二部分结尾文件即text_fooPart2.txt)。
最后一部分是doozy,这也是一项新要求。我需要验证一个文件是否已经存在同名,如果存在,我需要确保找到下一个可用名称。
如果我发现文件已经存在,我将循环递增一个重复的文件计数器,直到找到一个尚不存在的文件名。
#! /usr/bin/env perl
use strict;
use warnings;
use feature qw(say);
use File::Basename;
use File::Copy;
use File::Glob; # Improved Glob matching.
use constant {
DIRECTORY => 'summary',
};
# What files do you want to find?
# Do you want to find the immediate files or the
# files in the subdirectories?
#
# Let's do a more sophisticated pattern making sure we're catching
# the files we want.
#
my @text_files = glob('*/*.txt'); # Subdirectories only
mkdir DIRECTORY if not -d DIRECTORY; # Make this dir before the loop
for my $file ( @text_files ) {
my $dir_name = dirname $file;
my $file_name = basename $file;
say "DEBUG: On '$file'.";
#
# Let's make sure that the file name matches the expected
# pattern. If the substitution doesn't succeed, we assume
# this file shouldn't be copied, and skip it.
#
# I'm serching for a file that has the suffix '_vxxxx.txt' where
# 'xxxx' is some number. I remove the number and the letter `v`,
# and add in the directory name.
#
if ( not $file_name =~ s/_v(\d+)\.txt$/_$dir_name.txt/ ) {
warn qq("$dir_name/$file_name" has not been copied.");
next;
}
#
# If the name matches, make sure it's a file
#
if ( not -f $file ) {
warn qq("$file" is not a file and wasn't copied.");
next
}
#
# Now make sure file name is unique
#
if ( -f DIRECTORY . "/$file_name" ) { # File name already exists
say qq(DEBUG: Duplicate File '$file_name' detected!);
my $dup_file_counter = 2;
( my $file_no_suffix = $file_name ) =~ s/\.txt$//;
#
# Find a non-matching name
#
for (;;) {
my $new_file_name = $file_no_suffix . "_part_$dup_file_counter.txt";
say "DEBUG: New file name '$new_file_name'";
say qq(DEBUG: if ( not -e @{[DIRECTORY]} . "/$new_file_name" ) { );
if ( not -e DIRECTORY . "/$new_file_name" ) {
$file_name = $new_file_name;
last;
}
else {
$dup_file_counter += 1;
}
}
}
if ( not copy $file, DIRECTORY . "/$file_name" ) { # Check the outcome of this command.
warn qq(Could not copy file "$file" to directory ") . DIRECTORY . qq(".);
}
}
答案 1 :(得分:0)
在您使用@textfiles
而非@txtfiles
的循环中。使用strict
#!/usr/local/bin/perl
use File::Basename;
use strict;
use warnings;
my @txtfiles = glob("*.txt");
foreach my $file(@txtfiles){
my $dir = dirname($file);
$file = basename($file);
$file =~ s/(\d+)/$dir/; # renaming number with $dir
`mkdir -p summary` unless -d "summary";
`cp $file summary`;
}