Chapter 04Lesson 02~50 minutes

File Types, Metadata, stat, and file

A pathname is only a name. Reliable Linux work requires inspecting the object behind that name: its type, inode, ownership, mode, size, allocation, timestamps, link count, and content characteristics.

BeginnerMetadataHands-on lab

Learning objectives

By the end of this lesson

  • Identify regular files, directories, links, devices, sockets, and named pipes.
  • Interpret the principal fields reported by ls and stat.
  • Distinguish logical file size from allocated disk blocks.
  • Explain access, modification, status-change, and birth timestamps where available.
  • Use file and MIME inspection without treating filename extensions as authoritative.

1. A pathname names an object; it does not define the object

Linux does not require filename extensions to determine how the kernel opens a file. A name such as deploy.sh suggests intent to humans and tools, but the filesystem records an object type and metadata independently of that suffix. Content-inspection tools can make educated identifications, but applications still decide how to interpret data.

From pathname to inspected object
flowchart LR
  P["Pathname"] --> D["Directory entry"]
  D --> I["Inode and metadata"]
  I --> T["Object type"]
  I --> M["Mode, owner, size, times, links"]
  P --> F["file content inspection"]
  F --> G["Probable format or MIME type"]

2. Linux filesystem object types

The first character of an ls -l mode string identifies the object type. The remaining characters describe permissions, which Chapter 6 covers in depth.

MarkerObject typeTypical example
-Regular fileConfiguration, executable, archive, log, database
dDirectoryMapping of names to filesystem objects
lSymbolic linkObject containing another pathname
cCharacter device/dev/null, terminal devices
bBlock deviceDisks and logical block devices under /dev
pNamed pipe (FIFO)Filesystem-visible interprocess stream endpoint
sSocketLocal IPC endpoint such as a service control socket
printf 'Common object examples:\n'
ls -ld -- /etc /etc/os-release /dev/null /dev/loop0 2>/dev/null || true

printf '\nType markers only:\n'
find /dev -maxdepth 1 \( -type c -o -type b \) -printf '%y %p\n' 2>/dev/null | head

3. stat exposes the metadata record

stat reports information obtained from the filesystem. Output varies by implementation and filesystem, but GNU stat commonly shows device and inode numbers, type, mode, link count, ownership, size, allocated blocks, I/O block size, and timestamps.

target=/etc/os-release
stat -- "$target"

printf '\nMachine-oriented summary:\n'
stat --printf='path=%n\ntype=%F\ninode=%i\nlinks=%h\nmode=%A (%a)\nuid=%u gid=%g\nsize=%s bytes\nblocks=%b\nio_block=%o\nmtime=%y\nctime=%z\n' -- "$target"
Inode number

Filesystem-local object identity

Directory entries refer to inodes. The number is meaningful within a filesystem and can be reused after deletion.

Link count

Number of hard-link directory entries

For a regular file, data remains reachable while at least one hard link exists.

Mode and ownership

Type and access-control metadata

The mode contains the type and permission bits; UID and GID identify owner and group.

4. Logical size and allocated space are different

The size is the logical byte length visible to applications. The block count reflects allocated storage units as reported by the filesystem. Sparse files can have a large logical size while consuming relatively few blocks because unwritten regions are represented as holes.

lab="$HOME/devops-academy/linux/chapter04/lesson02"
mkdir -p -- "$lab"

regular="$lab/regular.bin"
sparse="$lab/sparse.bin"
dd if=/dev/zero of="$regular" bs=1M count=8 status=none
truncate -s 8M -- "$sparse"

printf '%-12s %12s %12s\n' NAME LOGICAL_BYTES ALLOCATED_BYTES
for path in "$regular" "$sparse"; do
  printf '%-12s %12s %12s\n' \
    "$(basename "$path")" \
    "$(stat -c %s "$path")" \
    "$(( $(stat -c %b "$path") * 512 ))"
done

printf '\ndu comparison:\n'
du -h -- "$regular" "$sparse"
du -h --apparent-size -- "$regular" "$sparse"
Capacity interpretation

Do not estimate filesystem consumption from ls -l size alone. Compression, sparse extents, copy-on-write, deduplication, filesystem metadata, and block allocation all affect actual storage use.

5. Understand the timestamp family

TimestampChanges whenOperational use
atimeFile data is accessed, subject to mount policy and cachingMay help access analysis, but is not guaranteed to update on every read
mtimeFile content is modifiedBuild tools, synchronization, cache invalidation, and change review
ctimeInode status changes, including metadata or content updatesNot creation time; useful evidence of a recent inode change
birth timeObject is created, when supported and exposedOptional historical field; may be unavailable

Changing content normally updates both mtime and ctime. Changing permissions or ownership updates ctime but not mtime. Reading may update atime depending on mount options such as relatime, strictatime, or noatime.

sample="$lab/timestamps.txt"
printf 'first version\n' > "$sample"
stat -c 'initial  atime=%x%nmtime=%y%nctime=%z%nbirth=%w' -- "$sample"

sleep 1
printf 'second version\n' >> "$sample"
stat -c 'modified atime=%x%nmtime=%y%nctime=%z%nbirth=%w' -- "$sample"

6. file inspects content signatures and structure

file uses tests and a magic database to classify content. It can recognize scripts by shebang, executable formats, compressed archives, images, text encodings, and many other formats. Its result is descriptive, not a security guarantee.

script="$lab/health-check"
printf '%s\n' '#!/usr/bin/env bash' 'printf "healthy\\n"' > "$script"
chmod u+x -- "$script"

cp -- /bin/ls "$lab/not-really-a-text-file.txt"
printf 'plain text\n' > "$lab/archive.tar.gz"

file -- "$script" "$lab/not-really-a-text-file.txt" "$lab/archive.tar.gz"
file --mime-type -- "$script" "$lab/not-really-a-text-file.txt" "$lab/archive.tar.gz"
Names are not validation

An uploaded file named report.pdf is not proven safe or even proven to be a PDF. Production validation may require content parsing, size limits, sandboxing, malware scanning, and policy checks.

7. Hands-on lab: build a filesystem metadata inventory

Create several object types and emit a tab-separated inventory suitable for later comparison or incident evidence.

set -u
root="$HOME/devops-academy/linux/chapter04/lesson02-inventory"
rm -rf -- "$root"
mkdir -p -- "$root/data"
printf 'alpha\n' > "$root/data/report.txt"
ln -s -- data/report.txt "$root/latest-report"
mkfifo -- "$root/events.fifo"

inventory="$root/inventory.tsv"
printf 'type\tinode\tlinks\tmode\tuid\tgid\tsize\tblocks\tmtime\tpath\n' > "$inventory"

find "$root" -mindepth 1 ! -path "$inventory" -print0 |
  while IFS= read -r -d '' path; do
    stat --printf='%F\t%i\t%h\t%A\t%u\t%g\t%s\t%b\t%Y\t%n\n' -- "$path"
  done | sort -t $'\t' -k10,10 >> "$inventory"

column -s $'\t' -t "$inventory" 2>/dev/null || cat "$inventory"
printf '\nContent classifications:\n'
file -- "$root/data/report.txt" "$root/latest-report" "$root/events.fifo"

Verification checklist

8. Common metadata mistakes

Treating ctime as creation time

On Linux, ctime is inode status-change time. Birth time is a separate optional field.

Using extensions as proof of format

Extensions are naming conventions. Inspect and validate content according to the risk.

Comparing inode numbers across filesystems

An inode number is only meaningful together with its filesystem or device identity.

Equating byte length with disk consumption

Sparse files, block rounding, compression, and copy-on-write can produce very different storage usage.

9. Knowledge check

Question 1. What does the first character in an ls -l mode string represent?

Question 2. Why is ctime not a creation timestamp?

Question 3. How can an 8 MiB sparse file consume far less than 8 MiB of allocated storage?

10. Summary

A pathname resolves through directory entries to a filesystem object and its metadata. Object type, inode, link count, mode, ownership, logical size, allocated blocks, and timestamps describe that object from different perspectives. stat reports filesystem metadata, while file inspects content patterns and should not be confused with definitive security validation.

Next lesson

Hard Links, Symbolic Links, and Inodes

You will use the inode model to explain why multiple names can refer to one file and how symbolic links differ.

11. Further reading

  • GNU Coreutils manuals for stat, ls, du, truncate, dd, and readlink.
  • Linux manual pages for stat, inode, file, find, fifo, and path_resolution.
  • file and libmagic documentation — content classification and magic tests.
  • Filesystem-specific documentation for sparse files, timestamps, extents, and copy-on-write behavior.
  • Filesystem Hierarchy Standard — conventional object placement across Linux systems.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.