Macos Perl:如何用UTF8可靠地外壳化文件名

Macos Perl:如何用UTF8可靠地外壳化文件名,macos,perl,Macos,Perl,我需要检查是否存在一些可能 名称中包含空格 名称中包含非ASCII(如Umlauts) 因为我使用了空格String::ShellQuote。然而,当在OSX上执行Umlauts时,这似乎不能很好地工作(还不知道其他操作系统): 输出: OU.tmp: created, EXISTS (says Perl), EXISTS (says ls), AOU.tmp: created, EXISTS (says Perl), EXISTS (says ls),

我需要检查是否存在一些可能

  • 名称中包含空格
  • 名称中包含非ASCII(如Umlauts)
因为我使用了空格
String::ShellQuote
。然而,当在OSX上执行Umlauts时,这似乎不能很好地工作(还不知道其他操作系统):

输出:

    OU.tmp:     created, EXISTS (says Perl), EXISTS (says ls), 
    AOU.tmp:    created, EXISTS (says Perl), EXISTS (says ls), 
    ÄÖÜ.tmp:    created, EXISTS (says Perl), EXISTS (says ls), 
    'ÄÖÜ.tmp':  created, EXISTS (says ls), 
    A OU.tmp:   created, EXISTS (says Perl), EXISTS (says ls), 
    'A OU.tmp': created, EXISTS (says ls), 
    Ä ÖU.tmp:   created, EXISTS (says Perl), EXISTS (says ls), 
    'Ä ÖU.tmp': created, EXISTS (says ls), 
问题:如何可靠地对可能包含扩展字符的文件名进行shell?


旁注:我假设这是一个非常好的OS-X典型UTF8规范化问题(UMLAUT的预合成与分解编码)。然而,我认为
String::ShellQuote
应该能够处理它。

据我所知,这些bug都是你的

让我们运行一下OU.tmp的两个循环:

首先是无引号的形式

  • 您可以打印一个OU.tmp
  • 运行
    触摸OU.tmp
    。这将创建(或更新)两个文件
    A
    OU.tmp
  • Touch已成功运行,因此您可以打印“已创建”
  • 您可以选中
    -e“A OU.tmp”
    。没有这样的文件(我相信您已经错误地转录了输出,因为这不是我在粘贴运行为darwin-thread-multi-2level构建的perl 5,version 12,subversion 4(v5.12.4)的代码时得到的)
  • 您可以运行
    ls A OU.tmp
    。这大致相当于运行
    ls A&&ls OU.tmp
    。这两个文件都存在,因此命令成功
  • 因为它起作用了,所以您打印“存在(表示ls)”
  • 下次通过循环时,Shell会使
    $file
    等于
    'A OU.tmp'

  • 您可以打印“OU.tmp”
  • 运行
    触摸'A OU.tmp'
    。这将创建(或更新)单个文件,名为
    a OU.tmp
    (因为空格已被引用)
  • Touch已成功运行,因此您可以打印“已创建”
  • 您检查
    -e“'A OU.tmp'”
    没有这样的文件。有一个文件名为
    a OU.tmp
    ,但没有一个文件名为
    'a OU.tmp'
    ,这正是您要求Perl查找的文件。(Perl不是您的shell,因此如果您给Perl shell引用的东西,它不会像shell那样解释它们
  • 运行
    ls'A OU.tmp'
    。这将检查名称中是否存在空格的单个文件,因此命令成功
  • 因为它起作用了,所以您打印“存在(表示ls)”
  • 中心问题似乎是您将Perl视为外壳上的一层,您通常应该选择使用Perl或外壳中的文件

    在Perl中:

    # do not use Shell_Quote
    foreach my $file ( @files, ) {
        open my $FH, ">>$file" or die;
        close $FH;
        print "yep!" if (-e $file);
    }
    
    在shell中(通过Perl):


    据我所知,这些虫子都是你的

    让我们运行一下OU.tmp的两个循环:

    首先是无引号的形式

  • 您可以打印一个OU.tmp
  • 运行
    触摸OU.tmp
    。这将创建(或更新)两个文件
    A
    OU.tmp
  • Touch已成功运行,因此您可以打印“已创建”
  • 您检查了
    -e“A OU.tmp”
    。没有这样的文件(我相信您转录了错误的输出,因为这不是我在粘贴运行针对darwin-thread-multi-2level构建的perl 5版本12 subversion 4(v5.12.4)的代码时得到的结果)
  • 运行
    ls A OU.tmp
    。这大致相当于运行
    ls A&&ls OU.tmp
    。这两个文件都存在,因此命令成功
  • 因为它起作用了,所以您打印“存在(表示ls)”
  • 下次通过循环时,Shell会使
    $file
    等于
    'A OU.tmp'

  • 您可以打印“OU.tmp”
  • 运行
    touch'A OU.tmp'
    。这将创建(或更新)一个名为
    A OU.tmp
    (因为空格已被引用)的文件
  • Touch已成功运行,因此您可以打印“已创建”
  • 您检查
    -e“'A OU.tmp'”
    没有这样的文件。有一个名为
    A OU.tmp
    的文件,但没有名为
    'A OU.tmp'
    的文件,这是您要求Perl查找的文件。(Perl不是您的shell,因此如果您给Perl shell引用的东西,它不会像shell一样解释它们。)
  • 运行
    ls'A OU.tmp'
    。这将检查名称中是否存在空格的单个文件,因此命令成功
  • 因为它起作用了,所以您打印“存在(表示ls)”
  • 中心问题似乎是您将Perl视为外壳上的一层,您通常应该选择使用Perl或外壳中的文件

    在Perl中:

    # do not use Shell_Quote
    foreach my $file ( @files, ) {
        open my $FH, ">>$file" or die;
        close $FH;
        print "yep!" if (-e $file);
    }
    
    在shell中(通过Perl):


    “只是不要在文件名中使用[spaces | umlauts |…]!(这个评论肯定会出现,所以我已经添加了它…)除了
    \0
    /
    之外,文件名中的所有内容都是有效的。代码应始终处理所有内容。停止在perl中使用shell代码。@jordanm:在OSX上,根据API级别,甚至文件名中允许使用
    /
    。(并在文件系统中透明地转换为
    ,反之亦然).Shell提示,“只是不要在文件名中使用[spaces | umlauts |…]”(这个注释肯定会出现,所以我已经添加了它…)除了
    \0
    /
    之外,文件名中的所有内容都是有效的。代码应始终处理所有内容。停止在perl中使用shell代码。@jordanm:在OSX上,根据API级别,甚至文件名中允许使用
    /
    。(并在文件系统中透明地转换为
    ,反之亦然).Shell提示,不过。非常感谢Nathaniel。(我对没有查找实际创建的文件感到非常羞愧…)没有必要
    打开
    关闭
    文件来测试文件是否存在“Perl不是您的shell,所以如果您给Perl shell引用的东西,它不会像shell那样解释它们。”这实际上是(m除外)
    
    # use only Shell_Quote
    foreach my $file ( @files, ) {
        `touch $file`;
        print "yes!" if (`ls $file`);
    }