The newline cat mystery
By Pete Freitag
I ran into a really strange problem today, whenever I would write a file it would show up as empty on my file system.
Here's a simplified version of my code:
var nl = chr(13); var csv = '"order_id","date"' & nl; csv &= '"1","2023-01-01"' & nl; fileWrite("/tmp/test.txt", csv);
I would then go to my terminal and type:
cat /tmp/test.txt
And it would not output anything, it appeared to be an empty file!
As a sanity check I added a throw
statement to the end of my code which read the file content.
var nl = chr(13); var csv = '"order_id","date"' & nl; csv &= '"1","2023-01-01"' & nl; fileWrite("/tmp/test.txt", csv); throw ( fileRead("/tmp/test.txt") );
Unfortunately this did not create any sanity because it would throw the contents of the file, but cat was saying that it was empty.
Now one thing that I should have noticed was that the file size was not zero bytes, so the file was actually not empty.
Cat is sneaky, and I used the wrong character code for newline
The problem was that I was using chr(13)
(carriage return) where I meant to use chr(10)
(new line). I've made this kind of mistake enough times to write a really detailed blog entry called What's the difference between ASCII Chr(10) and Chr(13)?, but this one still managed to baffle me for a while.
The other problem was that cat was not outputting anything in this case even though there was stuff in the file. It turns out that you can use cat -v
to show Display non-printing characters, and then it will actually output:
"order_id","date"^M"1","2023-01-01"^M
Still I find it very odd that cat
didn't show anything, perhaps it is because the carriage return, brings the cursor back to the beginning of the line, effectively erasing the line that was just output. The moral of the story that cat
will sometimes hide stuff from you, so you might need to check your file contents another way.
Update
As some have confirmed, the carriage return does indeed bring the cursor back to the beginning of the terminal, and will overwrite what was already printed. Here's an example that illustrates this:
echo "sanity\rodd" | cat
Which will output:
oddity
Now the reason I was not seeing anything is because the line I was outputting was shorter than my terminal prompt, so it overwrote it.
The newline cat mystery was first published on November 08, 2023.
The Fixinator Code Security Scanner for ColdFusion & CFML is an easy to use security tool that every CF developer can use. It can also easily integrate into CI for automatic scanning on every commit.
Try Fixinator
CFBreak
The weekly newsletter for the CFML Community
Comments
@verisimilidude - thanks for sharing your experiences with a printhead! I have been experimenting a bit more with this since I posted it and I will probably give some updates with more info / explanation. I do agree cat is not wrong, or weird it was me :-)
lineSeparator = createobject("java", "java.lang.System").getProperty("line.Separator");
NOTE: I found all java system settings referenced in one of your blog entries from 2004.
https://www.petefreitag.com/item/174.cfm