如何使用Perl';复制名称中带有特殊字符的文件;s文件::复制?

如何使用Perl';复制名称中带有特殊字符的文件;s文件::复制?,perl,file,special-characters,Perl,File,Special Characters,我正在尝试将一个位置中的所有文件复制到另一个位置,并使用File::copy模块和copy命令,但现在我面临的问题是,我的文件名为“代码>特殊字符 >它的ASCII值是“代码>253”/代码>,但是在UNIX文件系统中,它被存储为 >代码>,所以我的问题是,将>代码>复制或移动命令< /代码>在复制或移动到另一个位置时,考虑具有特殊字符的文件。不 如果是现在,那么可能的解决办法是什么 注意:我无法在unix中创建带有特殊字符的文件,因为特殊字符被替换为?,而我无法在Windows中创建文件,因为

我正在尝试将一个位置中的所有文件复制到另一个位置,并使用
File::copy
模块和
copy
命令,但现在我面临的问题是,我的文件名为“代码>特殊字符<代码> >它的ASCII值是“代码>253”/代码>,但是在UNIX文件系统中,它被存储为<代码> >代码>,所以我的问题是,将>代码>复制或移动命令< /代码>在复制或移动到另一个位置时,考虑具有特殊字符的文件。不 如果是现在,那么可能的解决办法是什么

注意:我无法在unix中创建带有特殊字符的文件,因为特殊字符被替换为
,而我无法在Windows中创建文件,因为在Windows中,特殊字符被替换为编码值,就像我在
和#253
中的情况一样

my $folderpath = 'the_path';
open my $IN, '<', 'path/to/infile';
my $total;
while (<$IN>) {
    chomp;
    my $size = -s "$folderpath/$_";
    print "$_ => $size\n";
    $total += $size;
}
print "Total => $total\n";
my$folderpath='the_path';

打开我的$IN,“以下脚本对我来说可以正常工作:

#!/usr/bin/perl

use strict; use warnings;
use autodie;

use File::Copy qw( copy );
use File::Spec::Functions qw( catfile );

my $fname = chr 0xfd;

open my $out, '>', catfile($ENV{TEMP}, $fname);
close $out;

copy catfile($ENV{TEMP}, $fname) => catfile($ENV{HOME}, $fname);
作为解决方法,我建议将所有不支持的字符转换为支持的字符。这可以通过多种方式实现。例如,您可以使用
URI::Escape

use URI::Escape;
my $new_file_name = uri_escape($weird_file_name);
更新:

下面是我如何能够复制文件的uft-8名称。我在窗户上。我过去常常使用短文件名。然后它被复制得很好:

use File::Copy;
use URI::Escape;
use Win32;

use utf8; ## tell perl that source code is in utf-9
use strict;
use warnings;

my $test_file = "IBMýSoftware.txt";
my $from_file = Win32::GetANSIPathName($test_file); ## get "short" name of file
my $to_file   = uri_escape($test_file); ## name with special characters escaped

printf("copy [%s] -> [%s]\n", $from_file, $to_file);
copy($from_file, $to_file);
在Windows上将所有文件改为新名称后,您将能够在linux上毫无问题地使用它们

以下是有关utf-8文件打开的一些提示:


字符253是
ý
。我猜在您的Unix系统上没有设置,或者只有最原始的回退区域设置有效,这就是您看到替换字符的原因。如果我猜对了,那么解决方案就是简单地将语言环境设置为某个值,最好设置为UTF-8语言环境,因为它可以处理所有字符,而Perl甚至不应该介入这个问题

> cat 3761218.pl
use utf8;
use strict;
use warnings FATAL => 'all';
use autodie qw(:all);

my $file_name = '63551_106640_63551 IBMýSoftware Delivery&Fulfillment(Div-61) Data IPS 08-20-2010 v3.xlsm';
open my $h, '>', $file_name;

> perl 3761218.pl
> ls 6*
63551_106640_63551 IBMýSoftware Delivery&Fulfillment(Div-61) Data IPS 08-20-2010 v3.xlsm
> LANG=C ls 6* # temporarily cripple locale so that the problem in the question is exhibited
63551_106640_63551 IBM??Software Delivery&Fulfillment(Div-61) Data IPS 08-20-2010 v3.xlsm
> locale | head -1 # show which locale I have set
LANG=de_DE.UTF-8


您正在从Unix复制到Windows吗?如果是这样,您还需要处理在Unix上合法但在Windows上不合法的字符。在一个极端的例子中,“\n”是Unix文件名中的合法字符。是。我正在从unix复制到windows。@以太:我无法获取带有特殊字符的文件大小。Downvote通常有一个原因,请提供一个原因,以便我可以改进此问题。您是否能够使用“”访问该文件不是转义码或特殊字符?我无法理解脚本,如果您给它添加一些注释,我将不胜感激。@Rachel脚本创建了一个文件,其名称仅由单个字符组成,字符代码为253。然后,将该文件从我的临时目录复制到我的主目录。问题中提到的脚本会打印所有文件的大小,但如果文件有一些特殊字符,它会忽略这些字符,令我惊讶的是,
#,@,$
由脚本获取,它确实给了我大小,但不考虑
ý
,我很难理解为什么会出现这种情况,我想知道你对此的想法,或者你是否能指导我进行一些适当的阅读,我将不胜感激。联合国大学:我试图理解教学流程,如果可能的话,如果您能在代码本身中添加更多注释,这样我就可以更好地理解它的工作原理,这将对我有所帮助。您能详细说明一下这一点吗,特别是为什么要使用两个perl文件以及Unix中的语言环境是如何设置的?我只使用一个perl文件我不知道您使用的是哪种Unix,所以我无法给出一个好的答案。然而,你可以很容易地自己找到答案。搜索或使用任何通用Web搜索引擎,如查找您需要的文档。我无法理解在
LANG=C ls 6*
locale | head-1 LANG=de_de.UTF-8
中发生了什么,你能否在代码中提供一些注释来解释这个场景,因为这将有助于我学习并更好地理解它。好的,我添加了一些注释。在普通命令前面加上变量赋值并没有什么特别的,这是shell编程的基础。阅读更多教程或书籍:嗯…感谢Daxim的更新,所以基本上只需将locale设置为UTF-8,问题将得到解决,我的脚本将能够获得文件的大小,但它无法使用特殊字符。我尝试在脚本中使用它,但当我运行脚本时,它只排除具有非常特殊字符的文件,有什么想法吗?@Rachel我猜脚本无法创建具有转换名称的文件。你能给出一个在函数调用后文件名失败的例子吗?
uri\u escape
63551\u 106640\u 63551 IBMý软件交付与实现(Div-61)数据IPS 08-20-2010 v3.xlsm
@Ivan:在我很难理解程序流程的情况下,你能解释一下与printf和copy相关的命令语句以及它是如何工作的吗?我已经更改了变量名称以获得更清晰的代码
printf
仅用于调试目的。其主要思想是,可以使用文件的“短”名称(使用
Win32::GetANSIPathName
)来复制/打开具有utf-8名称的文件。但这是Windows唯一的解决方案。接下来,我建议您生成没有特殊字符的新名称(使用
uri\u escape
)。文件复制到新名称后,您可以毫无问题地对其进行操作。