compare-object — Compare two collections by element — diff equivalent across all 5 shells
Equivalents in every shell
diff file1 file2GNU diff. Line-oriented; output uses `<` and `>` to indicate which file each differing line belongs to. `-u` for unified format (the standard for patches), `-r` to recurse directories, `-q` for "files differ" exit-only. For semantically-aware diffs (JSON, XML), reach for specialised tools (`jq`, `diff-so-fancy`).
diff file1 file2Same external `diff`. Zsh has the `(=)` glob qualifier to compare against a baseline pattern but it does not replace diff. For interactive review, zsh users often pair with `delta` (`brew install git-delta`, point `git diff` at it).
diff file1 file2Same `diff`. Fish has no native diff equivalent; the `string` builtin does line-set differences via `comm` + sort idioms but is awkward for general use. Reach for `diff` (POSIX) or `delta` (fancy display).
Compare-Object (Get-Content file1) (Get-Content file2)Aliased as `diff`, `compare`. Returns `[PSCustomObject]` with `.InputObject` and `.SideIndicator` (`<=` = only in reference, `=>` = only in difference, `==` = in both with `-IncludeEqual`). Compares by `[object].Equals()` by default — pass `-Property Name,Size` to compare structured records by named fields.
fc file1 file2Built-in `fc` (File Compare). `/N` line numbers, `/B` binary mode (byte-by-byte). Output format is verbose and not script-friendly. For automation prefer `comp` (returns errorlevel 1 on diff, 0 on match) or shell out to PowerShell.
Worked examples
Compare two text files line-by-line
diff file1.txt file2.txtCompare-Object (Get-Content file1.txt) (Get-Content file2.txt)fc file1.txt file2.txtShow only lines unique to file1
comm -23 <(sort file1) <(sort file2)Compare-Object (Get-Content file1) (Get-Content file2) | Where-Object SideIndicator -eq "<="Compare two objects by a specific property
Compare-Object $old $new -Property Name, StatusGotchas
- `Compare-Object` ignores ORDER by default — `Compare-Object @(1,2,3) @(3,2,1)` returns NO differences because both sets contain the same elements. For ordered comparison (diff-style), pass `-SyncWindow 0` or compare via index: `0..($a.Count-1) | ForEach-Object { if ($a[$_] -ne $b[$_]) { $_ } }`.
- `-IncludeEqual` adds rows for matched items (with `SideIndicator = '=='`) — useful for confirming overlap, otherwise omitted entirely. Without it, you cannot tell apart 'no matches' from 'perfect match' by row count alone (both yield zero output rows).
- When comparing complex objects without `-Property`, `Compare-Object` uses `.Equals()` — which on `[PSCustomObject]` is reference equality. Two structurally-identical custom objects will appear as different. Always pass `-Property` (or pre-project with `Select-Object`) for record comparison.
- `-CaseSensitive` flips the underlying comparator for strings — without it, `'Foo'` and `'foo'` are equal. Bash `diff` is case-sensitive by default; scripts porting bash workflows often need to add `-CaseSensitive` to match.
- `-PassThru` returns the original objects (annotated with a `SideIndicator` NoteProperty) instead of the wrapper `[PSCustomObject]`. Useful when you want to pipe the diffs straight to another cmdlet that expects the original type — e.g. `Compare-Object $oldServices $newServices -PassThru | Where-Object SideIndicator -eq '=>' | Start-Service`.