我正在编写一个脚本来批量重命名和复制基于csv文件的图像。 csv由第1列组成:旧名称和第2列:新名称。我想使用csv文件作为perl脚本的输入,以便它检查旧名称并使用新名称将副本复制到新文件夹中。 (我认为)我与图像有关的问题。它们包含utf8字符,如ß等。当我运行脚本时,它打印出来:Barfu├ƒg├ñsschen应该是Barfußgässchen,并出现以下错误:
Unsuccessful stat on filename containing newline at C:/Perl64/lib/File/Copy.pm line 148, <$INFILE> line 1.
Copy failed: No such file or directory at X:\Script directory\correction.pl line 26, <$INFILE> line 1.
我知道它与Binmode utf8有关,但即使我尝试一个简单的脚本(在这里看到它:How can I output UTF-8 from Perl?):
use strict;
use utf8;
my $str = 'Çirçös';
binmode(STDOUT, ":utf8");
print "$str\n";
打印出来:Ãirþ÷s
这是我的整个剧本,有人可以向我解释我哪里出错了吗? (它不是最干净的代码,因为我正在测试一些东西)。
use strict;
use warnings;
use File::Copy;
use utf8;
my $inputfile = shift || die "give input!\n";
#my $outputfile = shift || die "Give output!\n";
open my $INFILE, '<', $inputfile or die "In use / not found :$!\n";
#open my $OUTFILE, '>', $outputfile or die "In use / not found :$!\n";
binmode($INFILE, ":encoding(utf8)");
#binmode($OUTFILE, ":encoding(utf8)");
while (<$INFILE>) {
s/"//g;
my @elements = split /;/, $_;
my $old = $elements[1];
my $new = "new/$elements[3]";
binmode STDOUT, ':utf8';
print "$old | $new\n";
copy("$old","$new") or die "Copy failed: $!";
#copy("Copy.pm",\*STDOUT);
# my $output_line = join(";", @elements);
# print $OUTFILE $output_line;
#print "\n"
}
close $INFILE;
#close $OUTFILE;
exit 0;
答案 0 :(得分:3)
您需要确保流程的每个步骤都使用UTF-8。
创建输入CSV时,需要确保将其保存为UTF-8,最好不使用BOM。 Windows Notepad将添加一个BOM,因此请尝试使用Notepad ++,这样可以更好地控制编码。
您还遇到Windows控制台默认不符合UTF-8的问题。见Unicode characters in Windows command line - how?。可以使用chcp 65001
设置代码页,也可以不更改STDOUT编码。
就您的代码而言,关于新行的第一个错误可能是由于CSV中的新行。在chomp()
while (<$INFILE>) {
更新
要“解决”您需要使用正确的区域设置对文件名进行编码的文件,请参阅How do you create unicode file names in Windows using Perl和What is the universal way to use file I/O API with unicode filenames?。假设您正在使用Western 1252 / Latin,这意味着您的复制命令将如下所示:
copy(encode("cp1252", $old), encode("cp1252", $new))
另外,你的open也应编码文件名:
open my $INFILE, '<', encode("cp1252", $inputfile)
更新2:
当您在DOS窗口中运行时,请删除binmode(STDOUT, ":utf8");
并保留默认代码页。