佩尔 $! returns "Bad file descriptor" 一次 "No such file or directory" 当 运行 在调试模式下(不是 Perl 的调试模式)
Perl $! returns "Bad file descriptor" at once and "No such file or directory" when run in debug mode (not Perl's debug mode)
我有这个 Perl 代码:
foreach my $eachFile (@FileList)
{
$cmd = "xcopy /I /F /V /Y /R \"$ProjectPath\$eachFile\" \"$NewPath\\"";
print "\n\t$cmd\n";
my $result = system($cmd);
die "ERROR: Could not copy from $viewPath to $DLPath: $!" if ($result > 0);
}
在这段代码中,我放置了如下行:system("pause") if ($debug)
当 $debug 变量设置时暂停执行。
现在,上面的 xcopy 死掉了,因为一个文件不存在。但是,$!打印 : "Bad file descriptor" 当 运行 正常时,它打印 : "No such file or directory" 当我设置 $debug 变量时。
知道为什么 $!为两个实例提供不同的消息?
请参阅 system
的文档。 $!
仅在 system
本身失败并且 returns -1
时才有意义。否则,您必须通过拆分 $?
来自行弄清楚错误的含义。文档中的示例:
if ($? == -1) {
print "failed to execute: $!\n";
}
elsif ($? & 127) {
printf "child died with signal %d, %s coredump\n",
($? & 127), ($? & 128) ? 'with' : 'without';
}
else {
printf "child exited with value %d\n", $? >> 8;
}
因此您将 $?
右移 8 位,这就是 xcopy
编辑的错误代码 return。有 xcopy
个错误代码列表 here。
无论如何,这就是它应该的行为方式。在我的测试中:
my $ProjectPath = "c:\temp";
my @FileList = qw(aaa.txt asdf bbb.txt empty_dir beans.txt foo.pl);
my $NewPath = "c:\temp2";
foreach my $eachFile (@FileList) {
print "Copying $eachFile\n";
my $result = system(
qw(xcopy /I /F /V /Y /R), "$ProjectPath\$eachFile", "$NewPath\"
);
if ($? == -1) {
die "failed to execute: $!";
}
elsif ($? > 0) {
my $foo = $? >> 8;
print "Error code: $foo\n";
die "no files found to copy" if $foo == 1;
die "user pressed ctrl-c during copy" if $foo == 2;
die "initialization error" if $foo == 4;
die "disk write error writing" if $foo == 5;
die "unknown error";
}
}
当它发现我的临时目录中没有beans.txt
时报告"initialization error"。我不知道我需要做什么才能使 xcopy
return 成为 1
。 C'est la vie.
'\' 作为分隔符可能是问题所在,Unix 风格是'/'。
可以使用 Perl 时不要使用系统命令。否则,为什么要用 Perl 呢?
Perl 中有一个文件 copy
命令。它不是基本命令的一部分,但可以通过 File::Copy 模块获得。不要误以为这不是 Standard Perl 的一部分,因此不应使用。 File::Copy
模块已经存在很长时间了,它是您将 运行 安装的每个 Perl 安装的一部分。学习各种标准 Perl 模块,并将它们当作基本 Perl 的一部分来使用,因为它们是。
而且,不要害怕安装 CPAN Perl 模块。这些模块可以以奇妙的方式扩展 Perl(例如,解析 JSON、YAML 和 XML 文件或与万维网交互)。请记住,最好的 Perl 程序员非常懒惰,如果别人已经为他们编写代码,他们将不会编写代码。
要获得 copy
命令,我所要做的就是在我的 Perl 脚本的顶部添加 use File::Copy;
。
请注意,我的循环包含三行:
- 我通过
-f
命令验证文件是否存在。
- 我告诉你我在做什么(你的
xcopy
命令中有 /V
)
- 我复制文件。
另请注意,我更改了 您的变量名称。在 Perl 中,标准是使用下划线和小写字母作为变量名。此外,现在简单地说 for
而不是 foreach
是标准,这样可以节省您输入四个字符。
我使用启用 say
命令的 use feature qw(say);
pragma。我比 print
更喜欢它,因为 say
会自动将 \n
添加到行尾。这听起来像是一件小事,但是在你忘记 \n
几次之后,发现放置 \n
以你没有预料到的方式改变你的输出的情况,你会欣赏 say
命令.
我使用了另一个名为 File::Path
的模块,它为我提供了 make_path
命令。此命令是内置 mkdir
命令的扩展。但是,它使目录和所有父目录成为您想要的目录。如果你不需要担心制作整个路径,你可以简单地使用 mkdir
而不是包括 File::Path
.
use strict;
use warnings;
use feature qw(say);
use File::Copy;
use File::Path qw(make_path);
...
if ( not -d $project_path ) {
make_path $project_path
or die qq(Can't create directory "$project_path");
}
}
for my $file in ( @files ) {
if not ( -f "$project_path/$file" ) {
die qq(Can't copy non-existant file "$project_path/$file".);
}
say qq(Copying "$project_path/$file" to "$new_path");
copy "$project_path/$file", $new_path
or die qq(Can't copy "$file": $!);
}
是的,这没有回答您的直接问题。但是,我希望您了解 Perl 方式 做您想做的事,这样您就可以成为更好的 Perl 程序员。
我有这个 Perl 代码:
foreach my $eachFile (@FileList)
{
$cmd = "xcopy /I /F /V /Y /R \"$ProjectPath\$eachFile\" \"$NewPath\\"";
print "\n\t$cmd\n";
my $result = system($cmd);
die "ERROR: Could not copy from $viewPath to $DLPath: $!" if ($result > 0);
}
在这段代码中,我放置了如下行:system("pause") if ($debug)
当 $debug 变量设置时暂停执行。
现在,上面的 xcopy 死掉了,因为一个文件不存在。但是,$!打印 : "Bad file descriptor" 当 运行 正常时,它打印 : "No such file or directory" 当我设置 $debug 变量时。
知道为什么 $!为两个实例提供不同的消息?
请参阅 system
的文档。 $!
仅在 system
本身失败并且 returns -1
时才有意义。否则,您必须通过拆分 $?
来自行弄清楚错误的含义。文档中的示例:
if ($? == -1) {
print "failed to execute: $!\n";
}
elsif ($? & 127) {
printf "child died with signal %d, %s coredump\n",
($? & 127), ($? & 128) ? 'with' : 'without';
}
else {
printf "child exited with value %d\n", $? >> 8;
}
因此您将 $?
右移 8 位,这就是 xcopy
编辑的错误代码 return。有 xcopy
个错误代码列表 here。
无论如何,这就是它应该的行为方式。在我的测试中:
my $ProjectPath = "c:\temp";
my @FileList = qw(aaa.txt asdf bbb.txt empty_dir beans.txt foo.pl);
my $NewPath = "c:\temp2";
foreach my $eachFile (@FileList) {
print "Copying $eachFile\n";
my $result = system(
qw(xcopy /I /F /V /Y /R), "$ProjectPath\$eachFile", "$NewPath\"
);
if ($? == -1) {
die "failed to execute: $!";
}
elsif ($? > 0) {
my $foo = $? >> 8;
print "Error code: $foo\n";
die "no files found to copy" if $foo == 1;
die "user pressed ctrl-c during copy" if $foo == 2;
die "initialization error" if $foo == 4;
die "disk write error writing" if $foo == 5;
die "unknown error";
}
}
当它发现我的临时目录中没有beans.txt
时报告"initialization error"。我不知道我需要做什么才能使 xcopy
return 成为 1
。 C'est la vie.
'\' 作为分隔符可能是问题所在,Unix 风格是'/'。
可以使用 Perl 时不要使用系统命令。否则,为什么要用 Perl 呢?
Perl 中有一个文件 copy
命令。它不是基本命令的一部分,但可以通过 File::Copy 模块获得。不要误以为这不是 Standard Perl 的一部分,因此不应使用。 File::Copy
模块已经存在很长时间了,它是您将 运行 安装的每个 Perl 安装的一部分。学习各种标准 Perl 模块,并将它们当作基本 Perl 的一部分来使用,因为它们是。
而且,不要害怕安装 CPAN Perl 模块。这些模块可以以奇妙的方式扩展 Perl(例如,解析 JSON、YAML 和 XML 文件或与万维网交互)。请记住,最好的 Perl 程序员非常懒惰,如果别人已经为他们编写代码,他们将不会编写代码。
要获得 copy
命令,我所要做的就是在我的 Perl 脚本的顶部添加 use File::Copy;
。
请注意,我的循环包含三行:
- 我通过
-f
命令验证文件是否存在。 - 我告诉你我在做什么(你的
xcopy
命令中有/V
) - 我复制文件。
另请注意,我更改了 您的变量名称。在 Perl 中,标准是使用下划线和小写字母作为变量名。此外,现在简单地说 for
而不是 foreach
是标准,这样可以节省您输入四个字符。
我使用启用 say
命令的 use feature qw(say);
pragma。我比 print
更喜欢它,因为 say
会自动将 \n
添加到行尾。这听起来像是一件小事,但是在你忘记 \n
几次之后,发现放置 \n
以你没有预料到的方式改变你的输出的情况,你会欣赏 say
命令.
我使用了另一个名为 File::Path
的模块,它为我提供了 make_path
命令。此命令是内置 mkdir
命令的扩展。但是,它使目录和所有父目录成为您想要的目录。如果你不需要担心制作整个路径,你可以简单地使用 mkdir
而不是包括 File::Path
.
use strict;
use warnings;
use feature qw(say);
use File::Copy;
use File::Path qw(make_path);
...
if ( not -d $project_path ) {
make_path $project_path
or die qq(Can't create directory "$project_path");
}
}
for my $file in ( @files ) {
if not ( -f "$project_path/$file" ) {
die qq(Can't copy non-existant file "$project_path/$file".);
}
say qq(Copying "$project_path/$file" to "$new_path");
copy "$project_path/$file", $new_path
or die qq(Can't copy "$file": $!);
}
是的,这没有回答您的直接问题。但是,我希望您了解 Perl 方式 做您想做的事,这样您就可以成为更好的 Perl 程序员。