# diff — Compare Files and Directories

> Compare files and directories line by line with diff — unified, context and side-by-side output, recursive comparison and patch files.

Source: https://www.jpkc.com/db/en/cheatsheets/files-text/diff/

<!-- PROSE:intro -->
`diff` compares two files line by line and shows you exactly what changed – lines added, removed and modified. By far the most important output format is the unified format (`-u`), which Git and `patch` also use; alongside it are the context format (`-c`) and the two-column side-by-side view (`-y`). With `-r` you compare entire directory trees recursively, and by redirecting into a `.patch` file you create patches that `patch` can apply again later. Handy for scripting: the exit code of `diff` is `0` when the files are identical, `1` when they differ, and `2` on error.
<!-- PROSE:intro:end -->

## Basic Comparison

`diff <file1> <file2>` — Compare two files and show the differences in default (normal) format.

```bash
diff original.txt modified.txt
```

`diff -s <file1> <file2>` — Report when two files are identical.

```bash
diff -s config.ini config.ini.bak
```

`diff -q <file1> <file2>` — Only report whether files differ, not the actual differences.

```bash
diff -q v1.0/app.js v2.0/app.js
```

`diff <file1> <file2> > <patch>` — Save the diff output to a patch file.

```bash
diff original.c fixed.c > bugfix.patch
```

## Output Formats

`diff -u <file1> <file2>` — Unified format — the most common format, used by git and patch tools.

```bash
diff -u old/config.php new/config.php
```

`diff -u <file1> <file2> -L '<label1>' -L '<label2>'` — Unified format with custom labels instead of filenames in the header.

```bash
diff -u old.conf new.conf -L 'production' -L 'staging'
```

`diff -c <file1> <file2>` — Context format — shows changes with surrounding context lines.

```bash
diff -c original.py patched.py
```

`diff -y <file1> <file2>` — Side-by-side format — shows both files in parallel columns.

```bash
diff -y left.txt right.txt
```

`diff -y -W <width> <file1> <file2>` — Side-by-side format with a specific column width.

```bash
diff -y -W 120 left.txt right.txt
```

`diff --suppress-common-lines -y <file1> <file2>` — Side-by-side format showing only differing lines.

```bash
diff --suppress-common-lines -y old.conf new.conf
```

`diff -e <file1> <file2>` — Output an ed script that transforms file1 into file2.

```bash
diff -e original.txt modified.txt
```

## Context Control

`diff -U <n> <file1> <file2>` — Unified format with n lines of context (default is 3).

```bash
diff -U 5 old.js new.js
```

`diff -C <n> <file1> <file2>` — Context format with n lines of context.

```bash
diff -C 10 old.py new.py
```

`diff -U 0 <file1> <file2>` — Show only changed lines with no surrounding context.

```bash
diff -U 0 before.txt after.txt
```

## Whitespace & Formatting

`diff -b <file1> <file2>` — Ignore changes in the amount of whitespace.

```bash
diff -b old.py new.py
```

`diff -w <file1> <file2>` — Ignore all whitespace differences.

```bash
diff -w old.html new.html
```

`diff -B <file1> <file2>` — Ignore changes that only insert or delete blank lines.

```bash
diff -B old.css new.css
```

`diff -i <file1> <file2>` — Case-insensitive comparison.

```bash
diff -i readme.txt README.txt
```

`diff -Z <file1> <file2>` — Ignore trailing whitespace at the end of lines.

```bash
diff -Z old.txt new.txt
```

`diff -E <file1> <file2>` — Ignore changes due to tab expansion.

```bash
diff -E tabs.py spaces.py
```

`diff --strip-trailing-cr <file1> <file2>` — Strip trailing carriage returns (useful for Windows vs. Unix line endings).

```bash
diff --strip-trailing-cr unix.txt windows.txt
```

## Directory Comparison

`diff -r <dir1> <dir2>` — Recursively compare two directories and their contents.

```bash
diff -r project-v1/ project-v2/
```

`diff -rq <dir1> <dir2>` — Recursively compare directories and only report which files differ.

```bash
diff -rq /etc/nginx/ /etc/nginx.bak/
```

`diff -r --exclude='<pattern>' <dir1> <dir2>` — Compare directories but exclude files matching a pattern.

```bash
diff -r --exclude='*.pyc' src/ src-backup/
```

`diff -r --exclude-from=<file> <dir1> <dir2>` — Compare directories excluding patterns listed in a file.

```bash
diff -r --exclude-from=.diffignore old/ new/
```

`diff -r -x '*.log' -x '*.tmp' <dir1> <dir2>` — Compare directories excluding multiple patterns.

```bash
diff -r -x '*.log' -x '*.tmp' -x '.git' prod/ staging/
```

`diff -rq <dir1> <dir2> | grep 'Only in'` — Show files that exist in one directory but not the other.

```bash
diff -rq src/ src-backup/ | grep 'Only in'
```

## Patch Workflow

`diff -u <original> <modified> > <file.patch>` — Create a unified patch file from two files.

```bash
diff -u main.c main_fixed.c > fix.patch
```

`diff -ruN <dir1> <dir2> > <file.patch>` — Create a recursive patch for entire directories (-N treats missing files as empty).

```bash
diff -ruN project-v1/ project-v2/ > upgrade.patch
```

`patch < <file.patch>` — Apply a patch file to the current directory.

```bash
patch < fix.patch
```

`patch -p1 < <file.patch>` — Apply a patch stripping the first path component (common for git-style patches).

```bash
patch -p1 < upgrade.patch
```

`patch -R < <file.patch>` — Reverse (undo) a previously applied patch.

```bash
patch -R < fix.patch
```

`patch --dry-run < <file.patch>` — Test a patch without actually applying it.

```bash
patch --dry-run -p1 < upgrade.patch
```

## Colored & Visual Output

`diff --color <file1> <file2>` — Show differences with colored output (GNU diff).

```bash
diff --color old.conf new.conf
```

`diff --color=always <file1> <file2> | less -R` — Pipe colored diff output through less while preserving colors.

```bash
diff --color=always -u old.js new.js | less -R
```

`colordiff <file1> <file2>` — Use the colordiff wrapper for automatically colored output.

```bash
colordiff -u config.old config.new
```

`vimdiff <file1> <file2>` — Open both files in Vim with a side-by-side diff view.

```bash
vimdiff original.py modified.py
```

## Related Tools

`sdiff <file1> <file2>` — Side-by-side merge tool — interactive alternative to diff -y.

```bash
sdiff -o merged.txt left.txt right.txt
```

`diff3 <mine> <original> <yours>` — Three-way diff — compare three files (useful for merge conflicts).

```bash
diff3 my-branch.txt base.txt their-branch.txt
```

`comm <file1> <file2>` — Compare two sorted files line by line (shows unique and common lines).

```bash
comm -12 sorted1.txt sorted2.txt
```

`cmp <file1> <file2>` — Byte-by-byte comparison — reports the first difference found.

```bash
cmp binary1.dat binary2.dat
```

`wdiff <file1> <file2>` — Word-by-word diff — highlights individual word changes.

```bash
wdiff draft.txt final.txt
```

## Practical Examples

`diff -u <(sort file1.txt) <(sort file2.txt)` — Compare two files after sorting them (using process substitution).

`diff <(ssh host1 cat /etc/config) <(ssh host2 cat /etc/config)` — Compare a config file on two remote servers.

`diff -rq src/ deploy/ --exclude='.git' | sort` — Check which files differ between local source and deployed version.

`diff -u /dev/null <newfile>` — Create a patch that adds an entirely new file.

```bash
diff -u /dev/null src/newfeature.js > add-feature.patch
```

`diff <(xxd file1.bin) <(xxd file2.bin)` — Compare two binary files using hex dump output.

`diff -u <file1> <file2> | diffstat` — Show a summary of changes (insertions, deletions per file).

```bash
diff -ruN v1/ v2/ | diffstat
```

`diff -y -W 80 <(curl -s <url1>) <(curl -s <url2>)` — Compare the contents of two URLs side-by-side.

`find . -name '*.bak' -exec sh -c 'diff -q "$1" "${1%.bak}"' _ {} \;` — Compare each .bak file with its original counterpart.

<!-- PROSE:outro -->
## Conclusion

`diff` is the standard tool for making changes between two states visible – whether comparing two configurations, reviewing code or spotting drift between source and deployment. For everyday use, remember above all `-u` (unified, the Git/patch format), `-r` (recursive over directories) and `-q` (report only what differs). The exit code makes `diff` script-friendly: `0` identical, `1` different, `2` error. Some flags like `-Z`, `-E` or `--color` are GNU extensions and are missing on BSD/macOS. For output, `less -R` is worth it for paging with colors preserved; to filter the results reach for `grep`, and for scripted text edits reach for `sed`.

## Further Reading

- [GNU Diffutils manual](https://www.gnu.org/software/diffutils/manual/html_node/index.html) – official reference for all formats and options
- [Wikipedia: diff](https://en.wikipedia.org/wiki/Diff) – background on the diff utility and the unified format
<!-- PROSE:outro:end -->

## Related Commands

- [grep](https://www.jpkc.com/db/en/cheatsheets/files-text/grep/) – filter lines by pattern, often applied to diff output
- [sed](https://www.jpkc.com/db/en/cheatsheets/files-text/sed/) – replace and transform text in a scripted way
- [less](https://www.jpkc.com/db/en/cheatsheets/files-text/less/) – page through output, with -R for colors

