我需要检查是否存在某些文件
由于空格,我使用String::ShellQuote
。然而,在OSX上执行时,这对于变音符号似乎不能很好地工作(还不知道其他操作系统):
# 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规范化问题(Umlauts的预组合与分解编码)。不过,我认为String::ShellQuote
应该能够处理它。
答案 0 :(得分:5)
据我所知,这些错误都是你的。
让我们浏览A OU.tmp
的两个循环:
首先,不带引号的表格。
A OU.tmp
touch A OU.tmp
。这会创建(或更新)两个文件A
和OU.tmp
-e "A OU.tmp"
。没有这样的文件(我相信你错误地转录了你的输出,因为当我粘贴你的代码运行perl 5,版本12,颠覆4(v5.12.4)为darwin-thread-构建时,它不是我得到的多2level)ls A OU.tmp
。这大致相当于运行ls A && ls OU.tmp
。这两个文件都存在,因此命令成功。下次循环时,Shell_Quote使$file
等于'A OU.tmp'
'A OU.tmp'
touch 'A OU.tmp'
。这会创建(或更新)名为A OU.tmp
的单个文件(因为引用了空格)-e "'A OU.tmp'"
没有此类文件。有一个名为A OU.tmp
的文件,但没有名为'A OU.tmp'
的文件,这是您要求Perl查找的文件。 (Perl不是你的shell,所以如果你给Perl shell引用的东西,它就不会像shell那样解释它们。ls 'A OU.tmp'
。这将检查其名称中是否存在空格的单个文件,因此命令会成功。中心问题似乎是你将Perl视为外壳上的薄层。您通常应该选择使用shell中的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):
# use only Shell_Quote
foreach my $file ( @files, ) {
`touch $file`;
print "yes!" if (`ls $file`);
}