I agree in theory. In practice, programs evolve and code gets reused. Omitting free calls because you expect the code to exit rapidly is a recipe for disaster once you change your mind later. It's much easier to put this stuff in from the start than it is to retrofit it later.
> That's acceptable for a command-line program that will terminate quickly
No, it isn't; you don't know how quickly the program will terminate, in general, and it only takes one program running longer than you expect to eat a horrible amount of RAM.
I'll make a stand for it being bad style to free() memory when in any reasonable run of the program exit() would free just as effectively. This is simply arena allocation; some very excellent, well-regarded C code uses arenas and pools in the same idiom.
The downside to calling free(), apart from performance (malloc/free are extremely expensive), is that messing them up creates bugs that are much worse than simply holding on to some allocator metadata until the program hits exit().
The upside to calling free() is that it is a valuable lesson in understanding memory lifetimes for a beginner programmer. You can't know when it's good to omit free until you know what it means.
Messing them up exposes bugs that are likely to bite you in other ways. If you can't get malloc()/free() right, you don't really 'get' the flow control/data flow through your program yet and that is a problem.
Arena allocation is inherently simpler and less error-prone than demand-allocating and demand-freeing. It's not valid to say that arena allocation is "hiding" bugs; what it's doing is foreclosing on the possibility of having those bugs.
Virtually no large project has ever gotten malloc/free completely right in its first revision; for the past 20 years or so, most projects get this wrong to the tune of "remote code execution".
Not in general, no, but this particular program doesn't allocate a serious amount of memory (think `ls | less`) and doesn't contain any system calls which can reasonably block[1], so it's extremely unlikely to bite you in this case.
(I do think it's bad style, and would never write this program this way.)
[1] Assuming you stay away from the Zombie^W Network File System. But NFS mounts going away is bad news anyway, this program holding an extra KB of swappable memory doesn't really intensify the pain.
My strategy in c is as soon as I write the word "malloc" I figure out where to put the free.