Linux touch Command Deep Dive: From Timestamp Operations to Atomic File Creation#

When writing scripts, I often need to create empty files or update file timestamps. The touch command seems simple, but there’s more to it than meets the eye.

Core Functions of touch#

The touch command serves two main purposes:

  1. Create empty files - If the file doesn’t exist, create a zero-byte file
  2. Update timestamps - Modify access time (atime) and modification time (mtime)

Under the hood, it’s a wrapper around the utimensat() system call:

// Core logic of touch (simplified)
int touch(const char *path) {
    int fd = open(path, O_CREAT | O_WRONLY, 0666);
    if (fd < 0) return -1;
    close(fd);
    // Update timestamps to current time
    utimensat(AT_FDCWD, path, NULL, 0);
    return 0;
}

Three Types of File Timestamps#

Linux filesystems maintain three timestamps:

Timestamp Meaning View Command
atime Last access time ls -lu
mtime Last modification time ls -l
ctime Status change time ls -lc

Note: ctime is not creation time—it’s inode status change time. Changing permissions, owner, or link count updates ctime.

By default, touch updates both atime and mtime but doesn’t change ctime (unless the file needs to be created).

Common Options Explained#

-a: Update Access Time Only#

touch -a file.txt

Verify the result:

$ ls -lu file.txt
-rw-r--r-- 1 user user 0 May  9 00:50 file.txt

-m: Update Modification Time Only#

touch -m file.txt

Verify:

$ ls -l file.txt
-rw-r--r-- 1 user user 0 May  9 00:51 file.txt

-c: Don’t Create New Files#

By default, touch creates files that don’t exist. Use -c to prevent this:

touch -c nonexistent.txt  # Silently exits without error

This is useful in scripts to avoid accidentally creating files:

# Only update timestamps of existing config files
for f in *.conf; do
    touch -c "$f"
done

-t: Specify Exact Time#

Format: [[CC]YY]MMDDhhmm[.ss]

# Set to January 1, 2024, 12:00:00
touch -t 202401011200 file.txt

# Specify only month/day/hour/minute (current year)
touch -t 01011200 file.txt

# Down to seconds
touch -t 202401011200.30 file.txt

-d: Use Natural Language Dates#

More intuitive than -t:

touch -d "yesterday" file.txt
touch -d "2024-01-01 12:00:00" file.txt
touch -d "last week" file.txt
touch -d "2 days ago" file.txt

-r: Reference Another File’s Timestamp#

Make two files have identical timestamps:

touch -r reference.txt target.txt

This is common in backup scripts:

# Preserve original file's timestamp
touch -r "$original" "$backup"

Atomicity and Race Conditions#

touch uses the O_CREAT flag in a single system call. This is safer than:

# Not recommended: race condition
[ -f file.txt ] || echo "" > file.txt

# Recommended: atomic operation
touch file.txt

In high-concurrency environments, using touch for lock files is a common pattern:

LOCKFILE="/tmp/myapp.lock"

# Atomically create lock directory
if ! mkdir "$LOCKFILE" 2>/dev/null; then
    echo "Another instance is running"
    exit 1
fi

# Or use touch + flock
touch "$LOCKFILE"
exec 200>"$LOCKFILE"
flock -n 200 || exit 1

Practical Examples#

1. Batch Create Empty Files#

# Create 100 test files
for i in {1..100}; do
    touch "test_$i.txt"
done

# More concise approach
touch test_{1..100}.txt

2. Sync Directory Timestamp#

# Set directory timestamp to match newest file
LATEST=$(ls -t | head -1)
touch -r "$LATEST" .

3. Force Recompilation#

Build tools like Make rely on file timestamps to decide what needs recompiling:

# Force recompile all .o files
touch *.c

# Or just touch header files
touch *.h

4. Log Rotation Preprocessing#

# Create empty log file, preserving old log's timestamp
OLD_TS=$(stat -c %Y /var/log/app.log)
mv /var/log/app.log /var/log/app.log.old
touch -d "@$OLD_TS" /var/log/app.log

5. File Existence Check#

# Silently check if file exists and update timestamp
if touch -c "$1" 2>/dev/null; then
    echo "File exists, timestamp updated"
fi

Performance and Edge Cases#

Large Batch File Creation#

When creating many files, touch is more efficient than echo >:

# Create 10000 files comparison
time for i in {1..10000}; do touch "file_$i"; done
# real: 0m3.2s

time for i in {1..10000}; do echo > "file_$i"; done
# real: 0m8.7s

The reason: echo > requires opening, writing, and closing; touch only needs open(O_CREAT) and close.

Timestamp Precision#

Modern filesystems (ext4, xfs) support nanosecond timestamps:

$ stat file.txt
  File: file.txt
  Modify: 2024-01-01 12:00:00.123456789 +0800

However, some older filesystems (ext2, fat32) only have second-level precision—nanosecond timestamps get truncated.

By default, touch follows symbolic links:

ln -s target.txt link.txt
touch link.txt  # Updates target.txt's timestamp

Use -h to modify the symlink itself (filesystem support required):

touch -h link.txt  # Updates the symlink's own timestamp

Web Implementation: Simulating touch in Browser#

While browsers can’t directly access the filesystem, we can simulate timestamp operations with the File API:

interface FileWithTimestamp {
  name: string
  content: Blob
  lastModified: number  // Millisecond timestamp
}

function touchFile(file: FileWithTimestamp, time?: number): FileWithTimestamp {
  return {
    ...file,
    lastModified: time ?? Date.now()
  }
}

// Create empty file
function createEmptyFile(name: string): FileWithTimestamp {
  return {
    name,
    content: new Blob([''], { type: 'text/plain' }),
    lastModified: Date.now()
  }
}

// Usage example
const file = createEmptyFile('test.txt')
console.log(new Date(file.lastModified))  // Current time

// Set specific time
const touchedFile = touchFile(file, new Date('2024-01-01').getTime())
console.log(new Date(touchedFile.lastModified))  // 2024-01-01

Common Misconceptions#

Misconception 1: touch Can Modify ctime#

ctime can only be updated by changing inode attributes (chmod, chown). touch cannot directly modify ctime.

The only “indirect” way is to modify the file and restore:

# Not recommended: too many side effects
cp file.txt file.txt.bak
touch -r file.txt file.txt.bak
mv file.txt.bak file.txt

Misconception 2: touch Creates Zero-Size Files#

More precisely, touch creates zero-byte regular files. But there can be differences:

# Some filesystems have minimum block size
touch file.txt
ls -s file.txt  # May show 4K (depends on filesystem block size)

Misconception 3: touch Only Works on Files#

touch works on directories too:

mkdir mydir
touch mydir  # Updates directory's mtime

This is useful for triggering backup scripts or re-indexing.


Related tools: Linux find Command for File Search | Linux chmod Permission Calculator