cheat sheet

fc

Compare two text or binary files line-by-line or byte-by-byte and report their differences — the built-in Windows equivalent of Unix diff for quick file audits in cmd.exe.

fc — File Compare

What it is

fc (File Compare) is a built-in Windows command that compares two files and reports lines (or bytes) that differ between them. It works in two modes: ASCII mode for text files (default for .txt, .bat, and other text extensions) and binary mode (/B) for any file type. Use fc when you need a quick diff in a batch script or when you don't have a graphical diff tool installed. The PowerShell equivalent is Compare-Object; for richer diffs, use git diff or a dedicated tool.

Availability

fc ships as C:\Windows\System32\fc.exe on every Windows version.

cmd
fc /?

Output:

css
Compares two files or sets of files and displays the differences between them

FC [/A] [/B] [/C] [/L] [/LBn] [/N] [/OFF[LINE]] [/T] [/U] [/W] [/nnnn]
   [drive1:][path1]filename1 [drive2:][path2]filename2

Syntax

cmd
fc [options] file1 file2

Output: (diff report or "no differences encountered")

Essential options

SwitchMeaning
/BBinary comparison — byte by byte
/CCase-insensitive ASCII comparison
/LASCII mode (default for text files)
/NDisplay line numbers in ASCII comparison
/AAbbreviate output — show only first and last differing line of each block
/WCompress whitespace (tabs and spaces treated as single space)
/TDo not expand tabs to spaces
/UCompare as Unicode (UTF-16 LE) text files
/LBnSet the internal line buffer to n lines (default 100); increase for large sync blocks
/nnnnNumber of consecutive matching lines required to resync after a difference (default 2)

Basic ASCII comparison

ASCII mode compares files line-by-line, reports blocks of differing lines, and prints the surrounding context markers. If the files are identical, fc prints a success message and exits with code 0.

cmd
fc old.txt new.txt

Output:

ini
Comparing files old.txt and new.txt
***** old.txt
host=myhost
port=5432
***** new.txt
host=db.example.com
port=5432
*****
cmd
rem Identical files
fc base.txt base.txt

Output:

csharp
Comparing files base.txt and base.txt
FC: no differences encountered

Case-insensitive comparison (/C)

/C folds uppercase and lowercase when comparing lines, so ERROR and error are treated as identical.

cmd
fc /C expected.log actual.log

Output:

c
Comparing files expected.log and actual.log
FC: no differences encountered

Show line numbers (/N)

/N prepends the line number to each line in the diff report, making it easier to navigate to the difference in an editor.

cmd
fc /N config_v1.ini config_v2.ini

Output:

ini
Comparing files config_v1.ini and config_v2.ini
***** config_v1.ini
    12:  timeout=30
    13:  retries=3
***** config_v2.ini
    12:  timeout=60
    13:  retries=5
*****

Binary comparison (/B)

/B compares files byte by byte and reports the offset and differing byte values in hexadecimal. Use it for executables, images, or any non-text file.

cmd
fc /B firmware_v1.bin firmware_v2.bin

Output:

makefile
Comparing files firmware_v1.bin and firmware_v2.bin
00000A20: 4F 47
00000A21: 52 68
00000B00: 00 01

Whitespace-insensitive comparison (/W)

/W collapses runs of spaces and tabs into a single space before comparing, so indentation differences do not count as changes.

cmd
fc /W formatted.sql minified.sql

Output:

yaml
Comparing files formatted.sql and minified.sql
FC: no differences encountered

Abbreviated output (/A)

/A suppresses middle lines in a differing block, showing only the first and last line of each changed section — useful when you want a high-level summary across a large file.

cmd
fc /A /N report_old.txt report_new.txt

Output:

yaml
Comparing files report_old.txt and report_new.txt
***** report_old.txt
     3: Total records: 1024
    ...
    47: Generated: 2026-04-27
***** report_new.txt
     3: Total records: 1089
    ...
    47: Generated: 2026-04-28
*****

Using fc in scripts (exit codes)

fc exits with code 0 when files match and code 1 when they differ, making it usable in batch conditionals to detect unexpected changes.

cmd
@echo off
fc /B expected_hash.bin actual_hash.bin > NUL
if errorlevel 1 (
    echo MISMATCH: files differ.
    exit /b 1
) else (
    echo OK: files are identical.
)

Output:

makefile
OK: files are identical.

Common pitfalls

  1. ASCII mode for binary files produces garbage output — always use /B when comparing non-text files; without it, fc tries to parse bytes as text lines.
  2. Default resync window is 2 matching lines — if a block of changes is large and contains repeated content, fc may fail to resync and report the rest of the file as different; increase with /nnnn (e.g. /5).
  3. Line buffer limit is 100 lines — if a contiguous differing block exceeds 100 lines, fc may stop with "Resync Failed"; raise with /LB200 or higher.
  4. Exit code 1 means "differences found", not "error" — check errorlevel 1 with care; a true invocation error (bad path) also returns 1.
  5. fc is not a replacement for git diff — it has no context lines, no unified diff format, and no ignore patterns; for code review, use git diff or WinMerge.

Real-world recipes

Verify a downloaded file matches the original

cmd
@echo off
fc /B "C:\Downloads\setup.exe" "C:\Backups\setup.exe" > NUL
if errorlevel 1 (
    echo WARNING: downloaded file differs from backup.
) else (
    echo Checksum OK — files are byte-identical.
)

Output:

arduino
Checksum OK — files are byte-identical.

Diff two config snapshots and log the result

cmd
fc /N config_before.ini config_after.ini > C:\Logs\config_diff.txt
type C:\Logs\config_diff.txt

Output:

ini
Comparing files config_before.ini and config_after.ini
***** config_before.ini
    5:  max_connections=50
***** config_after.ini
    5:  max_connections=100
*****

Check that a deployed file matches the source

cmd
fc /B "C:\Source\myapp.exe" "C:\Deploy\myapp.exe" > NUL
if not errorlevel 1 echo Deploy matches source.

Output:

bash
Deploy matches source.

Comparison modes in depth

fc chooses ASCII or binary mode automatically based on file extension. Extensions associated with text content (.txt, .bat, .cmd, .ini, .log, .lst, .html, .htm, .asc, .c, .cpp, .h, .rc, .f, .for) trigger ASCII mode; anything else (including .exe, .dll, .bin, .zip, .jpg, .pdf) triggers binary mode. The /L and /B switches force the choice explicitly.

Forcing the wrong mode is the single most common source of confusing output:

cmd
rem Wrong: ASCII mode on a binary file produces "Resync Failed" or garbage
fc image.png image2.png

Output:

arduino
Comparing files image.png and image2.png
Resync Failed.  Files are too different.
cmd
rem Right: explicit binary mode
fc /B image.png image2.png

Output:

arduino
Comparing files image.png and image2.png
000000B8: 4F 47
cmd
rem Wrong: binary mode on a text file reports every byte difference (incl. line endings)
fc /B old.txt new.txt

Output:

makefile
Comparing files old.txt and new.txt
00000010: 4F 49
00000011: 4C 4E
...
cmd
rem Right: ASCII mode for text — fc reports lines, not bytes
fc old.txt new.txt

Output: (line-based diff)

Resync algorithm

After detecting a differing line, fc enters a search phase to find the next set of matching lines in both files so output can rejoin sensibly. The resync window is controlled by /nnnn — the number of consecutive matching lines required to declare the files "back in sync". The default is 2.

cmd
rem Default — 2 matching lines required to resync
fc a.txt b.txt

Output (default):

css
Comparing files a.txt and b.txt
***** a.txt
line5
***** b.txt
line5-modified
*****
cmd
rem Require 5 matching lines (more conservative; better for noisy diffs)
fc /5 a.txt b.txt

Output:

arduino
(may report fewer differences if the 5-line window absorbs them)
cmd
rem Require only 1 matching line (aggressive resync; more diff blocks)
fc /1 a.txt b.txt

Output:

vbnet
(produces more diff blocks because single matches count as resync)

If fc cannot find a resync within the line buffer (/LBn, default 100 lines), it gives up with:

sql
Resync Failed.  Files are too different.

This is not an error per se — it means the diff cannot be presented coherently. Increase /LB to allow larger differing blocks:

cmd
fc /LB500 longfile1.txt longfile2.txt

Output: (large diff)

Unicode comparison (/U)

/U instructs fc to read both files as UTF-16 LE (the encoding Windows calls "Unicode"). Without /U, fc treats UTF-16 files as binary because the alternating null bytes break ASCII parsing. UTF-8 files without a BOM read fine in ASCII mode; UTF-8 files with a BOM may emit a leading three-byte "garbage" line — strip the BOM first or compare with /B.

cmd
rem UTF-16 LE files (PowerShell `Out-File` default)
fc /U a.txt b.txt

Output:

css
Comparing files a.txt and b.txt
***** a.txt
hello
***** b.txt
hello world
*****
cmd
rem UTF-8 with BOM — strip BOM first for cleanest output
powershell -Command "(Get-Content a.txt -Raw) | Set-Content -Encoding utf8NoBOM a-clean.txt"
fc a-clean.txt b.txt

Output:

css
Comparing files a-clean.txt and b.txt
FC: no differences encountered

[!WARN] Mixing encodings between the two files causes fc to report spurious differences. Either convert both files to the same encoding first, or use a tool that understands encodings (PowerShell Compare-Object, git diff).

Tab and whitespace handling (/T and /W)

By default fc expands tab characters into spaces at the next multiple of 8 columns before comparing. /T disables this expansion — tabs are compared as 0x09 bytes. /W collapses runs of whitespace (spaces and tabs) into a single space, useful when the only difference is indentation.

Input AInput BDefault/T/W
foo\tbarfoo bar (8 spaces)matchdiffermatch
foo bar (3 spaces)foo bar (1 space)differdiffermatch
\tfoofoodiffer (leading tab → 8 spaces)differmatch (whitespace stripped)
cmd
rem Default: tab expansion, no whitespace collapse
fc indented.py reformatted.py

rem /T: tabs are bytes, not 8 spaces — useful for Makefile diffs
fc /T Makefile.old Makefile.new

rem /W: ignore indentation changes entirely
fc /W formatted.json minified.json

Output (fc /W):

yaml
Comparing files formatted.json and minified.json
FC: no differences encountered

Comparing sets of files

fc accepts wildcards in either filename position. With wildcards, fc compares each file in the source set against a same-named file in the destination set, producing a separate diff block per pair. Files present on only one side are reported as "FC: cannot open ... - No such file or directory".

cmd
rem Compare every .ini in two folders
fc C:\Config\*.ini C:\Backup\Config\*.ini

Output:

ini
Comparing files C:\Config\app.ini and C:\BACKUP\CONFIG\app.ini
FC: no differences encountered

Comparing files C:\Config\db.ini and C:\BACKUP\CONFIG\db.ini
***** C:\Config\db.ini
   port=5432
***** C:\BACKUP\CONFIG\db.ini
   port=5433
*****

FC: cannot open C:\Config\new.ini - No such file or directory

fc does not recurse — wildcards only match files in the immediate directory. For recursive comparison, drive it from a for /r loop or switch to PowerShell Compare-Object.

Driving fc from a for loop

cmd
@echo off
for %f in (C:\Source\*.txt) do (
    fc /N "%f" "D:\Dest\%~nxf" > NUL
    if errorlevel 1 (
        echo DIFF: %~nxf
    )
)

Output:

makefile
DIFF: config.txt
DIFF: readme.txt

For recursion, use for /r:

cmd
@echo off
for /r C:\Source %f in (*.cs) do (
    set "rel=%~pnxf"
    fc /N "%f" "D:\Dest%~pnxf:C:\Source=%" > NUL 2>&1
    if errorlevel 1 echo DIFF: %f
)

Output: (per-file diff indicators)

Exit codes

fc uses three exit codes; scripts that distinguish "differ" from "error" must inspect %ERRORLEVEL% carefully.

CodeMeaning
0Files identical
1Files differ (or invocation error such as missing file)
2Reserved (rarely seen)

The conflation of "differ" and "missing file" in code 1 is the chief pitfall — wrap the call to detect missing inputs explicitly:

cmd
@echo off
if not exist a.txt ( echo Missing a.txt & exit /b 2 )
if not exist b.txt ( echo Missing b.txt & exit /b 2 )

fc a.txt b.txt > NUL
if errorlevel 1 ( echo DIFFER & exit /b 1 )
echo IDENTICAL

Output:

code
IDENTICAL

PowerShell equivalent: Compare-Object

Compare-Object is the modern PowerShell cmdlet for diffing collections — including line collections read from files. It produces structured PSCustomObject output with SideIndicator (<=, =>, ==) that piped commands can filter and format.

powershell
# Basic line-by-line diff
Compare-Object (Get-Content old.txt) (Get-Content new.txt)

Output:

ini
InputObject              SideIndicator
-----------              -------------
port=5433                =>
port=5432                <=
powershell
# Case-insensitive comparison
Compare-Object (Get-Content a.txt) (Get-Content b.txt) -CaseSensitive:$false

Output: (lines that differ, ignoring case)

powershell
# Show unchanged lines too
Compare-Object (Get-Content a.txt) (Get-Content b.txt) -IncludeEqual

Output:

sql
InputObject     SideIndicator
-----------     -------------
common-line     ==
old-only        <=
new-only        =>
powershell
# Binary diff via byte arrays
Compare-Object `
    ([System.IO.File]::ReadAllBytes('a.bin')) `
    ([System.IO.File]::ReadAllBytes('b.bin'))

Output: (bytes that differ)

powershell
# Diff two directories by filename
Compare-Object `
    (Get-ChildItem C:\Source -Recurse -File | Select-Object -ExpandProperty Name) `
    (Get-ChildItem D:\Dest   -Recurse -File | Select-Object -ExpandProperty Name)

Output:

csharp
InputObject       SideIndicator
-----------       -------------
new-file.txt      <=
extra-file.log    =>

Compare-Object vs fc

FeaturefcCompare-Object
Output formatHuman-readable diff blocksStructured PSObjects
Line numbers/NAdd .ReadCount from Get-Content
Context linesnonenone (use git diff for context)
Whitespace handling/W, /TManual via .Trim() or regex
Encoding awareness/U only (UTF-16 LE)Pass -Encoding to Get-Content
Recursive directory diffnoyes (pipeline + -PassThru)
Binary diff/B (byte offsets)byte array comparison
Pipelinablenoyes
Exit codeuseful in cmduse if on output count

Use fc for quick interactive diffs in cmd.exe. Use Compare-Object when the diff result needs to drive further automation in PowerShell. For real source-code review, install git and use git diff --no-index a.txt b.txt, which provides unified diff format and context lines that neither built-in tool offers.

Comparing very large files

fc reads each file twice (once for content, once during resync), keeping a 100-line internal window by default. On multi-gigabyte files it is slow but does work; memory usage stays bounded.

For huge log files, prefer:

  • fc /LB10000 huge1.log huge2.log — increase resync buffer for large differing blocks.
  • where /R . huge*.log + hashes — if you only need "are they identical?", compute checksums instead:
cmd
certutil -hashfile huge1.log SHA256
certutil -hashfile huge2.log SHA256

Output:

bash
SHA256 hash of huge1.log:
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
CertUtil: -hashfile command completed successfully.

SHA256 hash of huge2.log:
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
CertUtil: -hashfile command completed successfully.

If the hashes match, the files are identical — much faster than fc /B on large files.

powershell
# PowerShell — same idea
(Get-FileHash huge1.log -Algorithm SHA256).Hash -eq (Get-FileHash huge2.log -Algorithm SHA256).Hash

Output:

graphql
True

Output format reference

ASCII diffs follow this layout:

css
Comparing files A and B
***** A
<context line>
<differing line 1>
<differing line 2>
***** B
<context line>
<differing line 1'>
<differing line 2'>
*****
  • ***** filename marks the start of a block from each file.
  • ***** (no name) closes the block.
  • With /N, lines are prefixed NN: text.
  • With /A, only the first and last differing line of each block are printed, separated by ....
  • Identical files produce a single line: FC: no differences encountered.

Binary diffs use:

vbnet
OFFSET: A-BYTE B-BYTE

The offset is a hex byte position from the start of file. Each difference is one line; there is no resync — fc /B always compares the entire file byte by byte.

fc and version control

fc is a poor fit for source-code review:

  • No unified-diff format.
  • No three-way merge.
  • No context lines beyond the differing block itself.
  • No file-rename detection.
  • No .gitignore awareness.
  • ASCII mode does not understand multi-line strings or mixed line endings (CRLF vs LF triggers spurious differences unless you preprocess).

For any code-level diff, prefer:

cmd
git diff --no-index a.txt b.txt

Output (git diff):

diff
diff --git a/a.txt b/b.txt
--- a/a.txt
+++ b/b.txt
@@ -3,3 +3,3 @@
 host=myhost
-port=5432
+port=5433
 user=alicedev

The unified format with context, +/- markers, and chunk headers is universally readable. fc remains useful for one-off non-source comparisons (config snapshots, build artefacts, downloaded binaries) where you don't want to involve git.

Common scenarios

Detect drift between dev and prod config

cmd
fc /N /C C:\Configs\dev\app.config C:\Configs\prod\app.config > C:\Logs\drift.txt
if errorlevel 1 (
    echo Drift detected — see C:\Logs\drift.txt
)

Output:

code
Drift detected — see C:\Logs\drift.txt

Verify a network download

cmd
rem Compare downloaded installer against a known-good local copy
fc /B "C:\Downloads\setup.exe" "C:\KnownGood\setup.exe" > NUL
if errorlevel 1 (
    echo Corrupt or different version
) else (
    echo Verified.
)

Output:

code
Verified.

Compare two database export snapshots

cmd
fc /W /C export_2026-05-01.sql export_2026-05-15.sql > schema-diff.txt
type schema-diff.txt | findstr /N "CREATE\|ALTER\|DROP"

Output:

makefile
12:CREATE TABLE audit_log (
89:ALTER TABLE users ADD COLUMN last_login DATETIME;

Confirm a file matches expected content

cmd
@echo off
set EXPECTED=C:\Templates\readme-template.txt
set ACTUAL=C:\Projects\myapp\README.md
fc /W /C "%EXPECTED%" "%ACTUAL%" > NUL
if errorlevel 1 (
    echo README has drifted from template
) else (
    echo README matches template
)

Output: (depends on contents)

Sources

References consulted while writing this article. Links open in a new tab.

  • Microsoft Learn — fc command reference — Authoritative flag list and parameter semantics used to build the Essential options table.
  • SS64 — fc — Cross-version comparison and historical syntax notes.

Tips

Use /B whenever you don't trust the file's extension. Forcing binary mode is harmless on text files (it shows byte-level diffs) but ASCII mode on binaries is a disaster.

For Unicode files (UTF-16 LE), always pass /U. PowerShell's default Out-File writes UTF-16 — diffing those without /U produces unreadable output.

When fc says "Resync Failed", increase the line buffer with /LB500 (or higher) before assuming the files really are too different.

For code review, install git and use git diff --no-index a b — unified diff format with context is dramatically more useful than fc's block format.

[!WARN] Exit code 1 means "differ OR error" — wrap with explicit if exist checks before calling fc if your script must distinguish a real diff from a typo in the file path.