touch creates a new, empty file if the file doesn't exist because that's what it was designed to do. The utility has to contain code to handle that case specifically. The utility appeared in Unix V7; its manual described it thus:
touch — update date last modified of a file
touch attempts to set the modified date of each file.
This is done by reading a character from the file and writing it back.
If a **file* does not exist, an attempt will be made to create it unless the
-c option is specified.
(I don't know what
touch did if the file was empty. The underlying system call came later.)
I don't know for sure why
touch was designed to make the file exist, but I suspect it's because of
make. Why would you want to set a file's modification time to the current time? There are cases where it could be useful to set the modification time to a particular time, but that ability came later, the original
touch could only set the modification time to the current time. A reason to do that is to re-run a
make rule that depends on the file.
That is, suppose you have a file
foo, and a makefile that declares a command to generate
foo. When you type
make bar, the command is executed and
bar is created. If
bar exists and is newer than
make bar does nothing, because
make assumes that
bar has already been generated. However, if
bar is older than
foo, make thinks that
bar is not up-to-date and needs to be regenerated.
But what if the rules to generate
bar have changed? Then you have two options:
rm bar; make bar
touch foo; make bar
You would need
foo to exist in order to generate
bar, otherwise the command would typically not work.
The “touch” terminology was also present in the
make -t bar would only pretend to run the commands, that is, it would set the modification time of
bar to the current time without actually running the command to generate
bar (you would do this if you thought that the changes to
foo shouldn't affect
touch utility was therefore a standalone version of the
make -t feature.