至于 cat 命令,如果列表中至少有一个文件不存在,它会返回 0 以外的退出代码,但继续执行,我也希望“perl”命令有同样的行为,它在继续执行时,不幸的是,当遇到一个或多个丢失的文件时,它不会返回非 0 的退出代码。
该解决方案由另一个主题提供https://stackoverflow.com/questions/22192300:
perl -p -i -e 'BEGIN{ -f $ARGV[0] or die"no file" } s/foo/bar/' non-existent-file.txt
当找不到文件时正确返回非 0 退出代码,但不会继续执行其他文件。事实上是这样的:
perl -p -i -e 'BEGIN{ -f $ARGV[0] or die"no file" } s/foo/bar/' non-existent-file.txt existent-file.txt
没有提供第二个文件的输出,而只提供第一个不存在的文件的错误。
我该如何解决这个问题?
答案1
我也不是一个 Perl 专家,但是你只评估第一个参数,并在文件不存在后立即终止你的脚本...如果第一个参数是一个不存在的文件,这既不会评估作为参数传递的所有文件,也不会继续处理其他文件。
因此,当您传递多个参数时,您的脚本将不会按预期工作(文件名)即可。
您需要首先使用例如评估所有命令行参数,foreach my $arg (@ARGV) { ... }
然后相应地设置退出代码,并在最后使用该代码退出。
即这样的:
perl -p -e 'my $exit_code; BEGIN{
foreach my $arg (@ARGV) {-f $arg or $exit_code = 2} }
END{exit($exit_code)}
s/foo/bar/' non-existent-file.txt existent-file.txt
注意(可能会节省你的时间): 据我所知,它die
没有自己的退出状态,也不会“直接”改变脚本的退出状态……因此,2
您看到的退出代码号实际上是-f $ARGV[0]
……no such file or directory
这些代码号是种类有限且各具特色...因此,在受控环境中手动分配/设置它们是完全没问题的,尽管传递的参数可能是目录,那么它可能会导致不同的错误编号,但这就是“受控”的意义所在,因为您可以更改-f
为-e
例如或使用条件进行双重评估,甚至添加您自己的扩展错误评估/包含代码来做你想做的事情。
此外,die
可以有一个副作用(例外)这将导致额外的错误代码,例如22
(无效的论点)从而污染你的脚本,如果你想保留一些实际的退出状态,这可能不是你想要的......看看为什么这里...然而你也许能够部分地控制/中和这种副作用(虽然可能不可靠...请exit
改用) 类似于eval{die "blabla" ... }
和,在这种情况下这也可能会直接改变脚本的退出状态。
不过,你也许可以同时使用die
和不是 exit
-f $ARGV...
并同时保留实际的退出状态,同时不会过早地终止脚本,如果您正确地将评估移动到一个END
块中,如下所示:
perl -p -e 'my @arr; BEGIN{@arr = @ARGV}
END{ foreach my $arg (@arr) { -f $arg or die"no file"} }
s/foo/bar/' non-existent-file.txt existent-file.txt
答案2
perl -p -i -e 'BEGIN { -f $ARGV[0] or push @nofile, $ARGV[0]; } END { die "no file: ". join ", ", @nofile if @nofile; } s/foo/bar/' non-existent-file.txt existent-file.txt