批量重命名目录中的
我有这样的名字有些文件的文件名:批量重命名目录中的
01_dpm_gsi_182.sl5
02_dpm_devel_gsi_182.sl5
03_DPM_DSI_181.sl5
04_globus_httpd_122.sl5
05_globus_httpd_client_cgi_132.sl5
如何重命名这些文件,让我得到这样一些事情:
01_dpmgsi_s2011e01.sl5
02_dpmdevelgsi_s2011e02.sl5
....
....
的最近我建议像这样:
#!/usr/bin/perl -n
if (/^([^_]+)_(.+)_([^.]+)([.].+)$/) {
my $s = $&;
my $x = $1;
my $y = $2;
my $z = 2011;
my $e = $4;
$y =~ s/_//g;
print "mv $s ${x}_${y}_s${z}e$x$e\n"
}
,然后用它是这样的:
# ls | perl -n reName.pl > output
# bash ./output
有没有更好的方法或单行来做到这一点,可能使用sed/awk?干杯!!
有没有必要使用bash脚本mv
的文件,perl可以做到这一点。下面的脚本使用File::Copy来达到这个目的。我已经将执行移动的行注释掉了,因此脚本可以先用输入进行测试。
代码:
use strict;
use warnings;
use v5.10;
#use File::Copy;
my $year = 2011;
for (@ARGV) {
my ($pre, @p) = split /_/;
my $ext = pop @p;
$ext =~ s/.*\./s${year}e$pre./;
my $new = join '_', $pre, (join '', @p), $ext;
say "old: $_";
say "new: $new";
say "------";
#move $_, $new or die $!;
}
用法:
perl script.pl *.sl5
如果您还没有版本5.10,交换say
与print
并添加一个换行符。
输出:
old: 01_dpm_gsi_182.sl5
new: 01_dpmgsi_s2011e01.sl5
------
old: 02_dpm_devel_gsi_182.sl5
new: 02_dpmdevelgsi_s2011e02.sl5
------
old: 03_DPM_DSI_181.sl5
new: 03_DPMDSI_s2011e03.sl5
------
old: 04_globus_httpd_122.sl5
new: 04_globushttpd_s2011e04.sl5
------
old: 05_globus_httpd_client_cgi_132.sl5
new: 05_globushttpdclientcgi_s2011e05.sl5
您不需要单独的bash脚本来执行重命名。 Perl有一个内置的rename
函数。有关文档,请参阅http://perldoc.perl.org/functions/rename.html。
我不打算评论正则表达式。改善它可能是可能的,但只要它正常工作,我不认为有任何需要改变它。
OK,你问一个班轮:
ls |xargs -n1|awk -F'[_.]' '{idx=$1;nf=$1"_";for(i=2;i<NF-1;i++)nf=nf$i; nf=nf"_s2011e"idx"."$NF;print "mv "$0" "nf;}'
这将打印所有mv
命令你。
如果目标名称全部正确,您可以检查输出。如果是的话,你只需在行尾添加"|sh"
,它会进行重命名。
测试(不含| SH,看输出)
kent$ ls |xargs -n1|awk -F'[_.]' '{idx=$1;nf=$1"_";for(i=2;i<NF-1;i++)nf=nf$i; nf=nf"_s2011e"idx"."$NF;print "mv "$0" "nf;}'
mv 01_dpm_gsi_182.sl5 01_dpmgsi_s2011e01.sl5
mv 02_dpm_devel_gsi_182.sl5 02_dpmdevelgsi_s2011e02.sl5
mv 03_DPM_DSI_181.sl5 03_DPMDSI_s2011e03.sl5
mv 04_globus_httpd_122.sl5 04_globushttpd_s2011e04.sl5
mv 05_globus_httpd_client_cgi_132.sl5 05_globushttpdclientcgi_s2011e05.sl5
这GNU sed的解决方案可能会为你工作:
sed 'h;s/[^_.]*\././;s/_//2g;s/^\(\([^_]*\)_[^.]*\)\./\1_s2011e\2e./;x;G;s/\(.*\)\n/mv -v \1 /' file
说明:
存储在保持空间(HS)的原始文件名。删除文件扩展前的数字。删除所有,但第一个_
。使用分组,新引用和添加文本来创建新文件名。交换到HS。追加新的文件名。添加mv -v
命令并删除嵌入的\n
。
正如已经说过的文件名可以让你起来 - 当心!
+1让我头晕目眩。 –
+2相同(但WOW !!) – MacUsers
omg,从不分析ls
的输出或构建由shell重新评估的查询。解析一个文件列表(由ls
输出)不可能在空白(或$ IFS变量中的任何内容)的情况下得到正确的结果,因此在任何时候都是一个尴尬的解决方案。同样,构建正确逃脱shell命令行几乎是不可能的。
为了保持与壳牌(这是这个任务仍然是一个很好的工具),使用通配符的文件,其中正确拆分参数:
for i in ./*
do
firstpart=${i%%_*}
num=${firstpart#./}
middlepart=${i#*_}
middlepart=${middlepart%_*}
middlepart=`printf %s "$middlepart" | tr -d _`
lastpart=s2011e"$num".sl5
echo mv "$i" "${firstpart}_${middlepart}_${lastpart}"
done
实际执行,删除echo
的最后一行。
+1不需要使用bash脚本 – Toto
简单易懂! +1 –