我有一个包含96个文件的文件夹,我想重命名。问题是每个文件名都需要一个独特的更改...而不是在每个名称的前面添加零或更改扩展名。搜索和替换是不切实际的。 以下是我想要更改的名称示例:
newSEACODI-sww2320H-sww24_07A_CP.9_sww2320H_sww2403F.fsa
newSEACODI-sww2320H-sww24_07B_CP.10_sww2320H_sww2403F.fsa
newSEACODI-sww2320H-sww24_07C_CP.11_sww2320H_sww2403F.fsa
newSEACODI-sww2320H-sww24_07D_CP.12_sww2320H_sww2403F.fsa
newSEACODI-sww2320H-sww24_07E_R.1_sww2320H_sww2403F.fsa
newSEACODI-sww2320H-sww24_07F_R.3_sww2320H_sww2403F.fsa
newSEACODI-sww2320H-sww24_07G_R.4_sww2320H_sww2403F.fsa
newSEACODI-sww2320H-sww24_07H_R.5_sww2320H_sww2403F.fsa
我想使用perl将上述名称分别更改为以下名称:
SEACODI_07A_A.2_sww2320H_2403F.fsa
SEACODI_07B_A.4_sww2320H_2403F.fsa
SEACODI_07C_H.1_sww2320H_2403F.fsa
SEACODI_07D_H.3_sww2320H_2403F.fsa
SEACODI_07E_H.6_sww2320H_2403F.fsa
SEACODI_07F_H.7_sww2320H_2403F.fsa
SEACODI_07G_Rb.4_sww2320H_2403F.fsa
SEACODI_07H_Rb.9_sww2320H_2403F.fsa
可以这样做吗?我有一个模糊的想法,我可能会创建一个包含新名称列表的文本文件,并将该列表称为@newnames。我会从当前文件名中创建另一个数组,并将其命名为@oldnames。然后我会做某种for
循环,其中@oldnames中的每个元素$ i都被@newnames中相应的$ i替换。
我不知道如何使用我当前的文件名制作数组,所以我不确定这个模糊的想法是否在正确的轨道上。我把我的文件与乱码名称保存在一个名为'oldnames'的目录中。以下是我尝试用该目录中的文件名创建一个数组:
#!/usr/bin/perl -w
use strict; use warnings;
my $dir = 'oldnames';
opendir ('oldnames', $dir) or die "cannot open dir $dir: $!";
my @file = readdir 'oldnames';
closedir 'oldnames';
print "@file\n";
以上似乎没有做任何事情。我迷路了。帮助
答案 0 :(得分:1)
下面:
#!/usr/bin/perl
use warnings;
use strict;
use autodie;
use File::Copy;
# capture script name, in case we are running the script from the
# same directory we working on.
my $this_file = (split(/\//, $0))[-1];
print "skipping file: $this_file\n";
my $oldnames = "/some/path/to/oldnames";
my $newnames = "/some/path/to/newnames";
# open the directory
opendir(my $dh, $oldnames);
# grep out all directories and possibly this script.
my @files_to_rename = grep { !-d && $_ ne $this_file } readdir $dh;
closedir $dh;
### UPDATED ###
# create hash of file names from lists:
my @old_filenames = qw(file1 file2 file3 file4);
my @new_filenames = qw(onefile twofile threefile fourfile);
my $filenames = create_hash_of_filenames(\@old_filenames, \@new_filenames);
my @missing_new_file = ();
# change directory, so we don't have to worry about pathing
# of files to rename and move...
chdir($oldnames);
mkdir($newnames) if !-e $newnames;
### UPDATED ###
for my $file (@files_to_rename) {
# Check that current file exists in the hash,
# if true, copy old file to new location with new name
if( exists($filenames->{$file}) ) {
copy($file, "$newnames/$filenames->{$file}");
} else {
push @missing_new_file, $file;
}
}
if( @missing_new_file ) {
print "Could not map files:\n",
join("\n", @missing_new_file), "\n";
}
# create_hash_of_filenames: creates a hash, where
# key = oldname, value = newname
# input: two array refs
# output: hash ref
sub create_hash_of_filenames {
my ($oldnames, $newnames) = @_;
my %filenames = ();
for my $i ( 0 .. (scalar(@$oldnames) - 1) ) {
$filenames{$$oldnames[$i]} = $$newnames[$i];
}
# see Dumper output below, to see data structure
return \%filenames;
}
自卸车结果:
$VAR1 = {
'file2' => 'twofile',
'file1' => 'onefile',
'file4' => 'fourfile',
'file3' => 'threefile'
};
运行脚本:
$ ./test.pl
skipping file: test.pl
Could not map files:
a_file.txt
b_file.txt
c_file.txt
文件结果:
$ ls oldnames/
a_file.txt
b_file.txt
c_file.txt
file1
file2
file3
file4
$ ls newnames/
fourfile
onefile
threefile
twofile
答案 1 :(得分:0)
你的代码有点奇怪,但应该有用。你是在“oldnames”目录或它上面的目录中运行它吗?你应该在它上面的目录中。更标准的写作方式是这样的:
#!/usr/bin/perl -w
use strict; use warnings;
my $dir = 'oldnames';
opendir ( my $oldnames, $dir) or die "cannot open dir $dir: $!";
my @file = readdir $oldnames;
closedir $oldnames;
print "@file\n";
这将填充@files
以及oldnames
,中的所有文件,包括'。'和'..'。您可能需要根据重命名的方式对其进行过滤。
答案 2 :(得分:0)
您可以使用rename执行此操作吗?如果我记得的话,它允许你使用perl
代码和表达式作为参数。
真正的答案是@chrsblck的答案,它做了一些检查,并没有弄得一团糟。
为了比较,这里是一个凌乱的单线,可能就足够了。它依赖于您提供的等效新文件名列表,这些文件名将以正确顺序重命名旧文件列表。也许对于您的情况(您不希望对文件名进行任何编程转换),您可以使用shell循环(请参阅本文末尾)从文件中读取新旧名称的列表。一个更好的perl
解决方案是将两个这些文件名列表分成两列,然后使用-a
开关@F
然后使用{ {1}}复制文件。
无论如何,下面是一些建议。
首先,进行设置:
File::Copy
如上所述排列文件,请复制所有内容:
% vim newfilenames.txt # list new names one per line corresponding to old names.
% wc -l newfilenames.txt # the same number of new names as files in ./oldfiles/
8 newfilenames.txt
% ls -1 oldfiles # 8 files rename these in order to list from newfilenames.txt
newSEACODI-sww2320H-sww24_07A_CP.9_sww2320H_sww2403F.fsa
newSEACODI-sww2320H-sww24_07B_CP.10_sww2320H_sww2403F.fsa
newSEACODI-sww2320H-sww24_07C_CP.11_sww2320H_sww2403F.fsa
newSEACODI-sww2320H-sww24_07D_CP.12_sww2320H_sww2403F.fsa
newSEACODI-sww2320H-sww24_07E_R.1_sww2320H_sww2403F.fsa
newSEACODI-sww2320H-sww24_07F_R.3_sww2320H_sww2403F.fsa
newSEACODI-sww2320H-sww24_07G_R.4_sww2320H_sww2403F.fsa
newSEACODI-sww2320H-sww24_07H_R.5_sww2320H_sww2403F.fsa
不漂亮:您需要perl -MFile::Copy -E 'opendir($dh , oldfiles); @newfiles=`cat newfilenames.txt`; chomp @newfiles; @oldfiles = sort grep(/^.+\..+$/, readdir $dh); END {for $i (0..$#oldfiles){copy("oldfiles/$oldfiles[$i]", "newfiles/$newfiles[$i]"); }}'
上的grep
和sort
来摆脱@oldfiles
并按顺序放置数组元素。而且一直存在打字错误可能造成混乱的风险,很难弄明白
如果您将旧名称和新名称放在几个文件中,您可以使用shell脚本执行此操作:
. ..
或仅for i in `cat ../oldfilenames.txt` ; do ; done; for n in `cat ../newfilenames.txt`; do cp $i $n;
进入包含旧文件的目录并执行:
cd
祝你好运!