使用csv文件使用utf8名称复制/重命名图像

Jan*_*Jan 5 csv perl utf-8

我正在编写一个脚本来批量重命名和复制基于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.
Run Code Online (Sandbox Code Playgroud)

我知道它与Binmode utf8有关,但即使我尝试一个简单的脚本(在这里看到它:如何从Perl输出UTF-8?):

use strict;
use utf8;
my $str = 'Çirçös';
binmode(STDOUT, ":utf8");
print "$str\n";
Run Code Online (Sandbox Code Playgroud)

它打印出来:Ã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;
Run Code Online (Sandbox Code Playgroud)

Ala*_*ack 3

您需要确保该过程的每一步都使用 UTF-8。

创建输入 CSV 时,需要确保将其保存为 UTF-8,最好没有 BOM。Windows 记事本将添加 BOM,因此请尝试使用 Notepad++,它可以让您更好地控制编码。

您还遇到 Windows 控制台默认不兼容 UTF-8 的问题。在 Windows 命令行中查看Unicode 字符 - 如何?。设置代码页chcp 65001或不更改 STDOUT 编码。

就您的代码而言,有关新行的第一个错误可能是由于 CSV 中的尾随新行造成的。添加chomp()while (<$INFILE>) {

更新:

要“寻址”文件,您需要在正确的区域设置中对文件名进行编码 - 请参阅如何使用 Perl 在 Windows 中创建 unicode 文件名使用带有 unicode 文件名的文件 I/O API 的通用方法是什么?。假设您使用的是 Western 1252 / Latin,这意味着您的复制命令将如下所示:

copy(encode("cp1252", $old), encode("cp1252", $new))
Run Code Online (Sandbox Code Playgroud)

另外,您的打开还应该对文件名进行编码:

open my $INFILE,  '<', encode("cp1252", $inputfile)
Run Code Online (Sandbox Code Playgroud)

更新2:

当您在 DOS 窗口中运行时,删除binmode(STDOUT, ":utf8");并保留默认代码页。