Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Incorrect command-line perl error value in $?

I am using command-line perl to perform a inplace substitution in a file. This is the code: (note the root perm with sudo)

sudo perl -i -pe "s/foo/bar/" config.txt

If this succeeds, 'echo $?' return 0. Now I make the file un-writable even for root using chattr like this:

sudo chattr +i config.txt

I run the same perl command and it fails with this error:

Can't remove config.txt: Operation not permitted, skipping file.

Which is fine. However, 'echo $?' still returns 0 in this case. Why is this so? Shouldn't it return a non-zero value indicating an error?

like image 955
Sujay Phadke Avatar asked May 10 '15 05:05

Sujay Phadke


1 Answers

The problem is that Perl does not come back with a non-zero exit status for this condition (sudo passes on the exit status of the command it was given), which is a bit vexing. You can work around the problem by recognizing that the line-reading loop is never entered if the file fails to be renamed and handle it with a flag:

sudo perl -i -ne 's/foo/bar/; print; $wrk = 1; }{ $wrk or exit 1' config.txt

The Eskimo greeting (or butterfly) "operator" }{ introduces an END block, in a way; what comes after it is executed when the loop reading lines from the file has ended. The way it works is described here.

The caveat is that this will also report an error if config.txt is empty. A shorter if a bit hackier way is to use the special $. line counter variable for the same purpose:

sudo perl -i -ne 's/foo/bar/; print; }{ $. or exit 1' config.txt
like image 135
Wintermute Avatar answered Oct 12 '22 13:10

Wintermute