1

可能性のあるファイルの存在を確認する必要があります

  • 名前に空白が含まれている
  • 名前に非ASCII(ウムラウトなど)が含まれている

空白のために私は使用しますString::ShellQuote。ただし、これはOSXで実行した場合(他のOSについてはまだわかりません)、Umlautsではうまく機能しないようです。

    # vim: ft=perl fenc=utf8
    # perl 5, version 12, subversion 4 (v5.12.4) built for darwin-thread-multi-2level

    use strict;
    use warnings;
    use String::ShellQuote;

    my @files = map {$_, shell_quote($_)} ("AOU.tmp", "ÄÖÜ.tmp", "A OU.tmp", "Ä ÖU.tmp");
    foreach my $file ( @files, ) {
        print "$file:\t";
        `touch $file`;
        print "created, " if( !$? ) ;
        print "EXISTS (says Perl), " if( -e $file );
        `ls -1 $file >/dev/null`;
        print "EXISTS (says ls), " if( !$? );
        print "\n";
    }

出力:

    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_quoteするにはどうすればよいですか?

補足:これは、これらの完全に優れたOS-Xの典型的なUTF8正規化の問題の1つであると思います(ウムラウトの合成済みエンコードと分解エンコード)。String::ShellQuoteそれでも、それで対処できるはずだと思います。

4

1 に答える 1

5

私の知る限り、バグはすべてあなたのものです。

次の2つのループを実行してみましょうA OU.tmp

まず、引用符で囲まれていない形式。

  1. 印刷しますA OU.tmp
  2. 実行しますtouch A OU.tmp。これにより、2つのファイルが作成(または更新)されAOU.tmp
  3. タッチが正常に実行されたため、「作成済み」と印刷します
  4. チェックし-e "A OU.tmp"ます。そのようなファイルはありません(darwin-thread用に構築されたperl 5、バージョン12、subversion 4(v5.12.4)を実行しているコードを貼り付けたときに得られるものではないため、出力を誤って転記したと思います-マルチ2レベル)
  5. 実行しますls A OU.tmp。これは、を実行するのとほぼ同じls A && ls OU.tmpです。これらのファイルは両方とも存在するため、コマンドは成功します。
  6. それが機能したので、あなたは「EXISTS(言うls)」を印刷します

次回ループを通過する$fileと、Shell_Quoteは次のようになります'A OU.tmp'

  1. 印刷します'A OU.tmp'
  2. 実行しますtouch 'A OU.tmp'A OU.tmpこれにより、(スペースが引用符で囲まれているため)という名前の単一のファイルが作成(または更新)されます。
  3. タッチが正常に実行されたため、「作成済み」と印刷します
  4. -e "'A OU.tmp'" そのようなファイルがないことを確認します。という名前のファイルがありますが、Perlに検索を求めているA OU.tmp名前のファイルはありません。'A OU.tmp'(Perlはあなたのシェルではないので、Perlのシェルで引用されたものを与えると、それらをシェルのように解釈することはありません。
  5. 実行しますls 'A OU.tmp'。これにより、名前にスペースが含まれている単一のファイルが存在するかどうかがチェックされるため、コマンドは成功します。
  6. それが機能したので、あなたは「EXISTS(言う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);
}

シェル内(Perl経由):

# use only Shell_Quote
foreach my $file ( @files, ) {
    `touch $file`;
    print "yes!" if (`ls $file`);
}
于 2013-01-14T15:23:26.840 に答える