我在dir中有一些文件,现在我想重命名文件(添加后缀和更改扩展名)。
输入:
XXIN123.timestamp.dat
XXIN123.timestamp.dat
XXIN123.timestamp.dat
XXIN123.timestamp.dat
XXIN123.timestamp.dat
最终输出:
XXX.123_456.newtimestamp.XXIN123.timestamp.csv
XXX.123_456.newtimestamp.XXIN123.timestamp.csv
XXX.123_456.newtimestamp.XXIN123.timestamp.csv
XXX.123_456.newtimestamp.XXIN123.timestamp.csv
首先在dir中搜索特定的模式文件,然后为它们添加后缀。
$oldpat = "XXIN123"
$newpat = "XXX.123_456"
然后将所有.dat
个文件重命名为.csv
它不能在第一次运行时运行,但在第二次运行中正常运行并覆盖第一个文件。
CODE:
use File::Copy;
use POSIX;
use strict;
my ( $dir, $oldpat, $newpat, $destdir );
my ( $oldname, $currenttime );
$dir = '/home/sd1/a1';
$destdir = '/home/sd1/a1/destination';
$oldpat = "XXIN123";
$newpat = "XXX.123_456";
$currenttime = strftime( "%Y%m%d%H%M%S", localtime );
opendir( DH, $dir ) || die "Cannot open $dir: $!";
my @files = readdir DH;
foreach (@files) {
$oldname = $_;
## Original find and replace
s/$oldpat/$newpat.$currenttime.$oldpat/;
next if ( !-f "$dir/$oldname" );
if ( !rename "$dir/$oldname", "$destdir/$_" ) {
warn "Could not rename $oldname\n"; #$oldname to $_: $!"
} else {
print "File $oldname renamed to $_\n";
}
close(DH);
# renaming
opendir( DIR, $destdir ) or die "Can't opendir $destdir: $!";
while ( defined( my $file = readdir DIR ) ) {
# ignore current and parent directory . and ..
next if $file =~ /^\.\.?$/;
my $new = $file;
# substitute new file extension
$new =~ s/\.dat$/\.csv/;
rename( $file, $new );
print "File $file renamed to $new\n";
}
close(DIR);
}
答案 0 :(得分:1)
有一个基于Perl的rename
命令 - 它出现在Camel Book的第1版中,但在较旧的SO问题中被引用并且可以在互联网上找到。 (您可能会发现它命名为prename
。)
你可以用它来完成这项工作:
rename "s/(.*)\.dat$/XXX.123_456.$(date +'%Y%m%d%H%M%S').\$1.csv/" *.dat
第一部分将文件名拆分为.dat
后缀和后缀之前的部分;替换部件使用date
命令计算的当前日期/时间,并使用ISO 8601日期/时间格式的变体进行格式化。它添加了固定前缀,新日期/时间,旧前缀和新后缀 - 并应用于当前目录中的所有.dat
文件。
(
mkdir junk
cd junk
for file in $(seq -f 'XXIN123.2014010118000%.0f.dat' 0 9); do cp /dev/null $file; done
ls -1
rename "s/(.*)\.dat$/XXX.123_456.$(date +'%Y%m%d%H%M%S').\$1.csv/" *.dat
ls -1
)
XXIN123.20140101180000.dat
XXIN123.20140101180001.dat
XXIN123.20140101180002.dat
XXIN123.20140101180003.dat
XXIN123.20140101180004.dat
XXIN123.20140101180005.dat
XXIN123.20140101180006.dat
XXIN123.20140101180007.dat
XXIN123.20140101180008.dat
XXIN123.20140101180009.dat
XXX.123_456.20140101181530.XXIN123.20140101180000.csv
XXX.123_456.20140101181530.XXIN123.20140101180001.csv
XXX.123_456.20140101181530.XXIN123.20140101180002.csv
XXX.123_456.20140101181530.XXIN123.20140101180003.csv
XXX.123_456.20140101181530.XXIN123.20140101180004.csv
XXX.123_456.20140101181530.XXIN123.20140101180005.csv
XXX.123_456.20140101181530.XXIN123.20140101180006.csv
XXX.123_456.20140101181530.XXIN123.20140101180007.csv
XXX.123_456.20140101181530.XXIN123.20140101180008.csv
XXX.123_456.20140101181530.XXIN123.20140101180009.csv
如果您需要我的rename
命令版本,请发送电子邮件(当然,这是我使用的,但它基于原始代码)。
如果你决定必须使用Perl来创建新的时间戳,你必须更加努力(并且非常非Perlish来重新发明轮子)。
答案 1 :(得分:0)
也许以下内容会有所帮助:
use strict;
use warnings;
use File::Basename;
use File::Copy;
use POSIX;
my $dir = '/home/sd1/a1';
my $destdir = '/home/sd1/a1/destination';
my $newpat = 'XXX.123_456';
my $oldpat = 'MHINOCC13';
my $currenttime = strftime( "%Y%m%d%H%M%S", localtime );
for my $currFile (<$dir/*.dat>) {
my $fileName = basename($currFile);
next unless $fileName =~ /^$oldpat-\d+-\d+[.]dat$/;
$fileName =~ s/dat$/csv/;
my $destFile = "$destdir/$newpat-$currenttime-$fileName";
print "Copying: $currFile -> $destFile\n";
if ( copy( $currFile, $destFile ) ) {
print "Success!\n\n";
}
else {
warn "Copy failed: $!\n\n";
}
}
这使用glob(<>
)来读取源目录。在for
循环中,File::Basename提取文件名,并使用正则表达式进行检查,以仅过滤所需的文件。接下来,文件名将更改为您想要的格式,然后使用File::Copy将源文件复制到目标目录中的新文件名。
请注意copy
例程将覆盖目标目录中任何同名的现有文件,因此使用此脚本需要您自担风险。