Perl脚本,使前8个字符全部大写,但不是整个文件名
我应该使用什么Perl脚本只将文件名中的前8个字符更改为all caps,而不是将整个文件名更改为all capsPerl脚本,使前8个字符全部大写,但不是整个文件名,perl,file,rename,Perl,File,Rename,我应该使用什么Perl脚本只将文件名中的前8个字符更改为all caps,而不是将整个文件名更改为all caps 下面是我如何设置它的: #!/usr/bin/perl chdir "directory path"; #@files = `ls *mw`; @files = `ls | grep mw`; chomp @files; foreach $oldname (@files) { $newname = $oldname; $newname =~ s/mw//; prin
下面是我如何设置它的:
#!/usr/bin/perl
chdir "directory path";
#@files = `ls *mw`;
@files = `ls | grep mw`;
chomp @files;
foreach $oldname (@files) {
$newname = $oldname;
$newname =~ s/mw//;
print "$oldname -> $newname\n";
rename("$oldname","$newname");
}
您可以使用此正则表达式:
my $str = 'Hello World!';
$str =~ s/^(.{8})/uc($1)/se; # $str now contains 'HELLO WOrld!'
那么:
#!/usr/bin/perl
use strict;
use warnings;
use File::Copy;
chdir'/path/to/directory';
# Find all files that contain 'mw'
my @files = glob("*mw*");
foreach my $file(@files) {
# skip directories
next if -d $file;
# remve 'mw' from the filename
(my $FILE = $file) =~ s/mw//;
# Change filename to uppercase even if the length is <= 8 char
$FILE =~ s/^(.{1,8})/uc $1/se;
move($file, $FILE);
}
#/usr/bin/perl
严格使用;
使用警告;
使用文件::复制;
chdir'/path/to/directory';
#查找包含“mw”的所有文件
my@files=glob(“*mw*”);
foreach my$文件(@files){
#跳过目录
下一个if-d$文件;
#从文件名中删除“mw”
(my$FILE=$FILE)=~s/mw/;
#将文件名更改为大写,即使长度始终为“检查系统调用的返回值”!
当您调用OS服务时,应该始终检查返回值
chdir EXPR
chdir文件句柄
chdir DIRHANDLE
chdir
如果可能,将工作目录更改为EXPR。如果省略EXPR,则更改为$ENV{HOME}
指定的目录(如果已设置);如果未设置,则更改为$ENV{LOGDIR}
指定的目录(在VMS下,还将检查变量$ENV{SYS$LOGIN}
)如果两者都未设置,chdir
不执行任何操作。成功时返回true,否则返回false。参见die下的示例
在支持fchdir(2)的系统上,可以传递文件句柄或目录句柄作为参数。在不支持fchdir(2)的系统上,传递句柄会引发异常
正如您在问题中所写,您的代码丢弃了重要信息:系统调用chdir
和rename
成功还是失败
提供有用的错误消息
在Perl中检查返回值的常用习惯用法的一个例子是
chdir $path or die "$0: chdir $path: $!";
错误消息包含三个重要信息位:
- 发出错误的程序
- 在本例中,它试图做什么,
chdir
- 为什么失败,
另请注意,如果错误消息未以换行符结尾,则die
还将显示程序控制所在的文件名和行号。当chdir
失败时,标准错误类似于
./myprogram: chdir: No such file or directory at ./myprogram line 3.
要使重命名
有希望,您必须保留$oldname
的值,因此,上面的代码立即将其复制到$newname
,并开始更改副本而不是原始副本。您将看到
($new = $old) =~ s/.../.../; # or /.../
在Perl代码中,因此它也是一个需要理解的重要习惯用法
定义用于字符串和正则表达式替换的方便转义序列:
\l
下一个字符仅小写
\u
titlecase(非大写!)仅下一个字符
\L
将所有字符小写,直到看到为止
\U
看到之前所有字符的大写字母
\Q
引用非单词字符直到\E
\E
结束案例修改或引用部分(以最后看到的为准)
上面的代码获取前八个字符(如果$newname
长度较短,则不超过八个字符),并将其替换为大写的对应字符
示例输出
请参阅正在运行的代码:
$ ls directory\ path/
defmwghijk mwabc nochange qrstuvwxyzmw
$ ./prog
$ ls directory\ path/
ABC DEFGHIJK QRSTUVWXyz nochange
$ls目录\路径/
defmwghijk mwabc nochange qrstuvwxyzmw
美元/进度
$ls目录\路径/
ABC-DEFGHIJK-qrstuvxyz-nochange
s/^(.{1,8})/\U$1/
将字符串的前八个字符设置为大写
use strict;
use warnings;
chdir "directory path" or die "Unable to change current directory: $!";
opendir my $dh, '.' or die $!;
my @files = grep -f && /mw/, readdir $dh;
foreach my $file (@files) {
(my $new = $file) =~ s/mw//;
$new =~ s/^(.{1,8})/\U$1/s;
print "$file -> $new\n";
rename $file, $new;
}
我想您的要求比您告诉我们的更多,例如文件扩展名的大写部分不匹配。我将匹配前八个字符,而不是匹配前八个字母:
其他一些注意事项:
- 您可以直接在Perl中进行全局编译,不需要
ls
- 看起来你正在剥离mv,所以我就这么做了。如果这不是你想要的,很容易改变
取代正则表达式,将可使用的4参数形式的前八个字符大写。这提供了原位替换
my $old = q(abcdefghij);
my $new = $old;
substr( $new, 0, 8, substr( uc($old), 0, 8 ) );
print "$old\n$new\n";
abcdefghij
ABCDEFGHij
使用rename
或File::Copy::move
(如M42所示)执行实际重命名。下面是我如何设置它的#!/usr/bin/perl chdir“目录路径”;#@files=ls*mw
;files=ls | grep mw
;chomp@files;foreach$oldname(@files){$newname=$oldname;$newname=~s/mw/;print“$oldname->$newname\n”重命名($oldname“,“$newname”);}#!/usr/bin/perl chdir“目录”;对于每个我的$file(@files){#将文件名更改为大写,即使长度<8 char$file=~s/^.{1,8}/uc和/e;move($file,$file);}从效率和安全角度来看,我不确定这是否正确格式化。最好尽可能避免使用经过计算的替换。此外,如果文件名少于8个字符,则代码不会将任何内容设置为大写。s/(^.{1,8})/\U$1/
很好用。@Borodin,你把/e和eval EXPR
混淆了s///e
实际上更像do BLOCK
。s///e
绝对没有安全问题,另一方面,它相当于s///eval/e
,而且它是有问题的。@Borodinr估算效率效益。s//\U$1//
和s//uc$1)/e
都是在编译s///时编译的(而不是在运行时),两者都打电话给uc
。这里有答案吗?@Borodin谢谢你的反馈。请建议我如何让我的答案更有帮助。OP自我描述为Perl的新手,所以我提供了额外的上下文。决定要包含多少背景信息是一个艰难的决定
use v5.14;
use utf8;
chdir "/Users/brian/test/";
my @files = glob( 'mw*' );
foreach my $old (@files) {
my $new = $old =~ s/\Amw(\pL{1,8})/\U$1/ir;
print "$old → $new\n";
}
my $old = q(abcdefghij);
my $new = $old;
substr( $new, 0, 8, substr( uc($old), 0, 8 ) );
print "$old\n$new\n";
abcdefghij
ABCDEFGHij