perl - 如果找不到错误文件,为什么退出代码0,我可以将其设为代码1吗?

时间:2016-08-28 04:59:44

标签: perl

我有几个逻辑AND命令,中间是一个perl命令,可以就地编辑文件。

echo before && \
perl -pe 's/foo/bar/g' -i qux && \
echo after

如果该文件不存在perl将死于“无法打开qux:没有这样的文件或目录”。但错误代码为0.这是一个问题,因为我不希望命令继续。换句话说,如果文件不存在,则不应打印'after'。为什么会发生这种情况?如何阻止它呢?

2 个答案:

答案 0 :(得分:4)

您可以使用perl -pe ... < file代替perl -pe ... file。在这种情况下,如果文件不存在甚至没有调用perl,shell就会抱怨。但这不能与-i开关一起使用。

或者,由于您要使用-i开关,因此在使用之前可能会检查该文件是否可写。并不是说这会检查qux是文件还是可写的,因为只有其中一个是不够的(也许还需要检查是否可读)。

[ -f qux ] && [ -w qux ] && perl -pe ... -i qux

答案 1 :(得分:2)

好的,所以...

正如对问题的评论中所提到的,perl退出0的原因是因为perl本身成功,即使perl执行的代码不是。为了让它以失败退出,那么,如果文件无法打开,我们需要找到一种方法使die(或显式exit具有非零状态)

但是perl -p围绕你的单行包裹了一个循环,那么我们可以这样做而不必在每一行重复测试吗?我们可以! perldoc perlrun告诉我们BEGINEND块允许我们在循环执行之前或之后控制。

但是我们仍然需要一种方法来判断文件是否已成功打开。为此,我们需要知道<>使用的文件句柄的名称,perldoc perlvar告诉我们ARGV

但是ARGV在读取时只是(可靠)神奇,所以我们不能只测试它是否被定义,因为(在我的快速测试中)它的总是定义,甚至如果文件丢失。所以我们必须从中读取。然后第一行丢失了。但是seek可以很容易地将其修复回文件的开头。

TL; DR 以及所有这些的结果:

echo before && \
perl -pe 'BEGIN { exit 1 unless <> ; seek ARGV,0,0 } s/foo/bar/g' -i qux && \
echo after

请注意,这仍然不是100%完美。如果文件存在,它也将die,但是为空。检查defined <>无法修复此漏洞并尝试<> ; die unless ARGV导致<>在文件不存在的情况下从STDIN读取。如果有人有办法让它正确检测空文件,我会非常有兴趣听到它!