为什么Windows中的Perl不能用元音变音重命名文件?

目录中有以下文件列表:

  1. 01出生 – 赞美 – 吻.flac
  2. 02 Wunschkind.flac
  3. 03你有它.flac
  4. 04在这个Hole.flac下
  5. 05Wälsungenblut.flac
  6. … N. 0N文件名

#是的,这些是Oomph的歌曲!

和下面的Perl程序:

use warnings; use strict; use utf8; use open qw( :encoding(UTF-8) :std ); my @dirnames; while ( (my $dirname = <>) =~ /\S/ ) { chomp($dirname); push (@dirnames, $dirname); } foreach my $dirname (@dirnames) { opendir (DIR, $dirname); while ( my $file = readdir(DIR) ) { if(length($file)>5) { print $file , "\n"; my $newfile; $newfile = substr($file, 0, 2); $newfile .= '.'; $newfile .= substr($file, 2); rename ($dirname . '\\' . $file, $dirname . '\\' . $newfile) or die $!; } } closedir DIR; } 

获取目录列表,并通过在数字后面添加点来重命名它们中的文件。

程序在所有文件上都能正常工作,但是当它尝试使用文件名中的变音符名称重命名文件时,Windows PowerShell和命令行都会抛出错误,指出在具有renamefunction的string处Permission denied

如何解决这个问题,伙计们?

UPD。 软件:

  • Windows 8 x64
  • ActiveState ActivePerl 1601(Perl 5.16)

Perl的readdir使用一个传统的接口(“ANSI”),因为它只能处理由unix遗留的字节组成的文件名。

“ANSI”接口使用称为代码页的单字节字符编码。 你的系统的代码页是1251 ,它不提供编码“ä”的方法,所以包含“ä”的文件名不能由readdir返回。

您需要避免使用“ANSI”接口( FindFirstFileA )并访问FindFirstFileW 。 这将提供UTF-16le的文件名,您可以传递给Win32API :: File的MoveFileExW 。 Win32 :: Unicode :: Dir的open + fetch就是fetch

这是一个令人沮丧的事态。 我一直想要解决它,但这将是一个广泛的项目。

 use utf8; use Win32 qw( ); BEGIN { binmode(STDOUT, ':encoding(cp'.Win32::GetConsoleOutputCP().')'); binmode(STDERR, ':encoding(cp'.Win32::GetConsoleOutputCP().')'); } 

 use strict; use warnings; use feature qw( say ); use open ':encoding(UTF-8)'; use Encode qw( encode ); use Win32::Unicode::Dir qw( mvtreeW ); use Win32API::File qw( MoveFileExW ); my $dir_qfn = '.'; my $wdir = Win32::Unicode::Dir->new(); $wdir->open($dir_qfn) or die("Can't open $dir_qfn: ".$wdir->error()); for ($wdir->fetch()) { next if /^\.\.?\z/; next if length() <= 5; say; my $o_fn = $_; s/^..\K/./s; my $n_fn = $_; MoveFileExW( encode('UTF-16le', "$dir_qfn/$o_fn\0"), encode('UTF-16le', "$dir_qfn/$n_fn\0"), 0, # or MOVEFILE_REPLACE_EXISTING ) or die("Can't rename $o_fn to $n_fn: $^E\n"); } $wdir->close(); 

您正在阅读目录,就好像它是UTF-8一样,但是您确实是在使用Windows-1252编码。 失去use open qw(...) ,它应该工作。

你有访问“rename.pl”吗? 你可以做

 perl rename.pl "s/^(\d\d)/$1./" *flac