Error handling in one-liners

From: =?UTF-8?B?Q2hyaXN0b3BoIEJ1w59lbml1cw==?=

Date: March 25, 2012 02:56

Subject: Error handling in one-liners

Message ID: 4F6E08E3.8010902@cpan.org

March 25, 2012 02:56Error handling in one-liners

Hi, let me start with this question: Does anyone know the difference between these two commands: perl -i -plwe 's/foo/bar/' file sed -i 's/foo/bar/' file One hint: Would you use it on a production system? The difference is how they behave when a write error occurs, like when the disk is full. Perl will silently replace the file with an empty file, which is really bad behavior imho. One might argue that this is not a bug because perl behaves exactly as specified in the documentation (perldoc perlrun; perldoc -f print; etc). However when you think about it, many people think of "perl -p" as a cooler version of sed and use it the same way. For instance, if you take a Debian system and search the postinst scripts in /var/lib/dpkg/info, you will find stuff like this: (hplib.postinst:) perl -p -i -e 's:^(\s*ppd=).*$:\1/usr/share/ppd/hplip/HP:' /etc/hp/hplip.conf So what should one do about this? Either 1) Change perl and the documentation (Don't know how exactly it should be changed) 2) Change the one-liners to include proper error handling. However this would really take the brevity out of them, which is probably what most script authors value in perl one-liners 3) Use sed instead of perl 4) Ignore the problem / just make sure that your disks don't fill up. Actually many people tend to respond this way when I question how stuff behaves after write errors (which is why I started this message with those silly questions). Note this does not only affect -i. There are also scripts like this: perl -plwe 's/foo/bar/' file > file2 && rm file This would be the safe version: perl -plwe 's/foo/bar/; END { close STDOUT or die $! }' file > file2 && rm file Not a real beauty in a shell-script though. Explicitly closing stdout is what most shell tools like sed, sort, etc. do (according to what I observed using strace). In the case of -i, an "END" cannot be used, especially if more than one file are specified. I don't know if this has been discussed before, since I guess things have been this way for quite a while. I could not find anything on Google. If it has, I would like to raise this issue for re-discussion :) By the way, to actually see the questionable behavior in action, you may use the following commands on a Linux system: mkdir a sudo mount -o size=1 -t tmpfs tmpfs a cd a seq 9999 > file # will write until it fills up cat file # non-empty output perl -i -plwe 's/foo/bar/' file # no error cat file # empty output Cheers, Christoph P.S.: Afaik sed -i is only available in recent GNU sed versions.



