我有几个逻辑AND命令,中间是一个perl命令,可以就地编辑文件。
echo before && \
perl -pe 's/foo/bar/g' -i qux && \
echo after
如果该文件不存在perl将死于“无法打开qux:没有这样的文件或目录”。但错误代码为0.这是一个问题,因为我不希望命令继续。换句话说,如果文件不存在,则不应打印'after'。为什么会发生这种情况?如何阻止它呢?
答案 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
告诉我们BEGIN
和END
块允许我们在循环执行之前或之后控制。
但是我们仍然需要一种方法来判断文件是否已成功打开。为此,我们需要知道<>
使用的文件句柄的名称,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
读取。如果有人有办法让它正确检测空文件,我会非常有兴趣听到它!