touch — create empty files and rewrite timestamps

Give the filesystem a poke: touch creates a file from thin air or stamps a precise time on one that already exists.

The fastest way to make 'file not found' vanish — and the tool every build system quietly weaponizes against stale timestamps.

What it does

touch does two jobs. With no flags it creates a file if it doesn't exist, and if it does exist it updates that file's modification time to right now — without touching its contents. With the -a/-m/-d/-t/-r flags it becomes a precise timestamp editor: you can set only the access time, only the modification time, or pin both to an exact moment. Under the hood it's a thin wrapper around the utimensat() syscall, which is why it's instant even on enormous files — it never reads or writes the data, just the metadata.

Why it matters

Makefiles and build tools decide what to rebuild by comparing file mtimes — so a wrong timestamp means a build that silently recompiles everything or skips work it should redo. Touch is how you fix that by hand: bump a header so dependents rebuild, backdate a config to stop a daemon from reloading it. It's also the standard trick for stubbing out nonexistent files when testing scripts, and for creating a batch of empty placeholder files in a directory without a text editor in sight. A two-letter command that fixes builds and unblocks tests is worth knowing cold.

Examples

$ touch server.pid
$ ls -l server.pid
$ stat -c '%n  size=%s  mtime=%y' server.pid
$ touch server.pid
$ ls -l server.pid
-rw-rw-r-- 1 kmail kmail 0 Sep 21 09:01 server.pid
$ stat -c '%n  size=%s  mtime=%y' server.pid
server.pid  size=0  mtime=2026-09-21 09:01:08.756841359 +0200

The headline use: a fresh, zero-byte file that didn't exist a second ago — verified live on this box. Pidfiles and lock files are born exactly like this.

$ echo 'port = 8080' > app.conf
$ touch app.conf
$ stat -c 'mtime=%y' app.conf
$ echo 'port = 8080' > app.conf
$ touch app.conf
$ stat -c 'mtime=%y' app.conf
mtime=2026-09-21 09:01:08.759841403 +0200

Touching an existing file updates its mtime but leaves the contents untouched — that's the whole point when you need a build tool to think a file just changed.

$ touch -m -d '2024-01-15 08:30:00' backup.tar
$ ls -l --time-style=full-iso backup.tar
$ touch -m -d '2024-01-15 08:30:00' backup.tar
$ ls -l --time-style=full-iso backup.tar
-rw-rw-r-- 1 kmail kmail 0 2024-01-15 08:30:00.000000000 +0100 backup.tar

-m limits the change to modification time; -d accepts human-readable dates. Handy for making an archive sort logically when your restore order depends on 'newest first'.

$ touch -t 202601011200.00 deploy.log
$ ls -l --time-style=full-iso deploy.log
$ touch -t 202601011200.00 deploy.log
$ ls -l --time-style=full-iso deploy.log
-rw-rw-r-- 1 kmail kmail 0 2026-01-01 12:00:00.000000000 +0100 deploy.log

-t takes the compact [[CC]YY]MMDDhhmm[.ss] form — no quotes around the value needed. Great for backdating logs out of a buggy deployment window.

$ touch -c not-here.file
$ echo "exit=$?"
$ touch a.log b.log c.log && ls a.log b.log c.log
$ touch -c not-here.file
exit=0
$ touch a.log b.log c.log && ls a.log b.log c.log
a.log
b.log
c.log

-c (aka --no-create) won't create files that don't exist — still exit 0, so it's safe in scripts. Multiple names? touch makes them all in one call, no loop needed.

$ echo hi > base.txt
$ touch -r base.txt newfile.txt
$ stat -c 'mtime=%y' base.txt newfile.txt
$ echo hi > base.txt
$ touch -r base.txt newfile.txt
$ stat -c 'mtime=%y' base.txt newfile.txt
base.txt mtime=2026-09-21 09:01:08.764841475 +0200
newfile.txt  mtime=2026-09-21 09:01:08.764841475 +0200

-r copies timestamps from a reference file. One-liner to sync a whole tree's times to a master file, verified: both now share base.txt's mtime.

Flags

FlagMeaning
touch FILECreate the file if absent; otherwise update mtime (and atime) to now. The zero-argument default.
-aUpdate only the access time (atime), leaving mtime alone — a read-side metadata stamp.
-mUpdate only the modification time (mtime) — the one build systems actually compare.
-c / --no-createDon't create a file that doesn't exist. Still exits 0, so it's safe to use blindly in scripts.
-d "DATE"Set both timestamps to a human-readable date, e.g. "2024-01-15 08:30:00" or "yesterday". GNU coreutils parses it.
-t [[CC]YY]MMDDhhmm[.ss]Set timestamps from a compact numeric form, e.g. -t 202601011200.00 — no quotes required.
-r REF_FILECopy the timestamps from another file instead of supplying them from scratch.

A relic of Unix's empty-file convention

touch has been in Unix since the very early Bell Labs days — it's in Research Unix V7 (1979) as one of the core file utilities. In the era before databases, an empty file doubling as a marker or a lock was a normal pattern, and touch was how you minted one. The name is literal: you poke the file's timestamps, the way you'd touch something to check it's still there, without moving its contents.

From AT&T utility to build-system linchpin

Stuart Feldman's make (1976) formalized the rule that a target needs rebuilding if any prerequisite is newer than it is — which made file timestamps the backbone of compiling for decades. touch grew from a novelty into the escape hatch that make, makefiles, and later build caches all lean on: force a rebuild, suppress one, or fix a clock skew that made make rebuild the world. GNU coreutils (still maintained today, version 9.4 on this box) kept it as near-identical to the original as a 45-year-old command gets.

Fun facts

Pros

Cons

Takeaways