2012-11-23 76 views
5

我正在處理腳本以基於csv文件批量重命名和複製圖像。 csv由第1列:舊名稱和第2列:新名稱組成。我想將csv文件用作perl腳本的輸入,以便它檢查舊名稱並使用新名稱將副本複製到新文件夾中。 (我認爲)我遇到的問題與圖像有關。它們包含UTF8字符,如SS等。當我運行該腳本,它打印出這一點:Barfu├ƒg├ñsschen它應該是Barfußgässchen和以下錯誤:使用csv文件複製/重命名utf8名稱的圖像

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"; 

它打印出這一點:艾爾特÷小號

這是我的整個腳本,可有人向我解釋我要去哪裏錯誤? (它不是最乾淨的代碼,因爲我正在測試的東西)。

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

關於你的第一個片段:.pl文件本身是用utf8編碼的嗎? 'use utf8' pragma告訴Perl你的源代碼是用utf8編寫的。它不涉及數據。 – simbabque

+0

你打印輸出到哪裏?一個Linux shell?另外,你是如何創建文件? –

+0

我可以確認你的第一個代碼片段在LANG設置爲'en_GB.UTF-8'並且Putty設置爲UTF-8的情況下可以在我的Linux shell上正常工作。我在同一個shell中使用VIM創建了該文件。 –

回答

3

您需要確保流程的每一步都使用UTF-8。

當您創建輸入CSV時,您需要確保它保存爲UTF-8,最好沒有BOM。 Windows記事本將添加BOM,因此請嘗試使用Notepad ++,以便更好地控制編碼。

您還有一個問題,即默認情況下,Windows控制檯不符合UTF-8標準。請參閱Unicode characters in Windows command line - how?。或者將代碼頁設置爲chcp 65001或者不要更改STDOUT編碼。

根據您的代碼,有關新行的第一個錯誤可能是由於從CSV尾隨的新行。後while (<$INFILE>) {

更新添加chomp()

「解決」,你需要你的編碼文件名在正確的區域設置文件 - 請參閱How do you create unicode file names in Windows using PerlWhat is the universal way to use file I/O API with unicode filenames?。假設您使用西1252 /拉丁美洲,這意味着當你複製命令看起來像:

copy(encode("cp1252", $old), encode("cp1252", $new)) 

而且,你也開放應該編碼文件名:

open my $INFILE, '<', encode("cp1252", $inputfile) 

更新2:

當您在DOS窗口中運行時,請刪除binmode(STDOUT, ":utf8");並保留默認的代碼頁。

+0

我在notepad ++中創建了CSV格式的utf8,但沒有BOM,所以不應該如此。我正在檢查你現在給我的其他2條建議。 – Jan

+0

在'while(<$INFILE>){'做了第一個錯誤的訣竅之後添加'chomp;'。首先設置代碼頁,然後再次嘗試腳本不會改變任何內容。我仍然收到郵件複製失敗。我打印新舊名稱,可以看到舊名稱不正確,這就是爲什麼它與實際文件不匹配並且失敗 – Jan

+0

請參閱更新re:文件名編碼 –