ログやリスト、書き出したデータの中から重複した行を取り除いて、ユニークな行だけにしたい——PowerShellなら数行で実現できます。ただし、重複行を消す方法はいくつかあり、それぞれ「並び順が変わるかどうか」「大文字小文字を区別するかどうか」が違います。ここを知らずに使うと、思った結果になりません。
とくに注意したいのがGet-Uniqueです。名前から「重複を消すコマンド」に見えますが、Get-Uniqueは隣り合った重複しか消さないため、事前にソートしておかないと重複が残ってしまいます。この記事では、実機のPowerShell 5.1で確認しながら、重複行の削除方法を整理します。
- 並び順を保ちたいなら
Select-Object -Unique(出現順のまま重複を削除)。 - 並べ替えてよいなら
Sort-Object -Unique(ソートしつつ重複を削除)。 Get-Uniqueは隣接した重複しか消しません。使うなら必ず先にSort-Objectします。Select-Object -Uniqueは大文字小文字を区別、Sort-Object -Uniqueは区別しません。- ファイルに書き戻すときは
Set-Content -Encodingでエンコードを指定します。
重複した「ファイル」を中身で探すなら重複ファイルの検出(Get-FileHash)、絞り込みや並べ替えの基本はWhere-Object・Select-Object・Sort-Object、ファイルの読み書きはファイル・フォルダ操作もあわせて参考になります。
3つの方法と使い分け
重複行を消す主な方法は3つあります。実機でbanana, apple, banana, cherry, apple, bananaという6行に対して試した結果は次のとおりです。
Select-Object -Unique→banana, apple, cherry(出現順を保って重複削除)Sort-Object -Unique→apple, banana, cherry(ソートして重複削除)Get-Unique(ソートなし) → 6行のまま(隣接重複が無いので何も消えない)
並び順を維持したいか、ソートしてよいか、で選ぶのが基本です。順番に見ていきます。
順序を保って重複行を削除する Select-Object -Unique
もとの並び順を保ったまま重複を消したいならSelect-Object -Uniqueです。最初に出てきた行を残し、2回目以降の同じ行を削除します。ログのように順番に意味があるデータに向いています。
# ファイルを読み込み、出現順のまま重複行を削除 Get-Content "C:\data\list.txt" | Select-Object -Unique # 例: banana, apple, banana, cherry, apple, banana # → banana, apple, cherry(最初の出現順を保持)
実機でも、Select-Object -Uniqueはbanana, apple, cherryと、最初に登場した順番を保ったまま重複を削除しました。並び順が意味を持つデータ(時系列のログ、入力順のリストなど)では、この方法が第一候補になります。
ソートしてよいなら Sort-Object -Unique
並び順が変わってもよいなら、Sort-Object -Uniqueが簡単です。ソートと重複削除を一度に行います。アルファベット順・五十音順などに整列したい場合に便利です。
# ソートしながら重複行を削除 Get-Content "C:\data\list.txt" | Sort-Object -Unique # 例: banana, apple, banana, cherry, apple, banana # → apple, banana, cherry(ソートされる)
実機でも、Sort-Object -Uniqueはapple, banana, cherryと、並べ替えたうえで重複を削除しました。最終的にソート済みのユニークなリストがほしいなら、これが一番手軽です。逆に、元の順番を保ちたいときには使えません(並び替わってしまうため)。
【罠】Get-Uniqueは隣接した重複しか消さない
名前が紛らわしいのがGet-Uniqueです。「ユニークを取得」という名前から重複削除に使えそうですが、Get-Uniqueは隣り合った(連続した)重複しか消しません。離れた位置にある重複は残ってしまいます。
# NG: ソートせずに Get-Unique → 隣接重複が無いので何も消えない Get-Content "C:\data\list.txt" | Get-Unique # banana, apple, banana, ... → そのまま残る(重複が消えない!) # OK: 先に Sort-Object してから Get-Unique Get-Content "C:\data\list.txt" | Sort-Object | Get-Unique # → apple, banana, cherry(ソートで重複が隣接し、消える)
実機で確認したところ、banana, apple, banana, cherry, apple, bananaをそのままGet-Uniqueに渡しても、6行が一切減りませんでした。Get-Uniqueは「直前の行と同じなら消す」という動きのため、同じ行が隣り合っていないと重複と認識しないのです。一方、Sort-Object | Get-Uniqueのように先にソートして同じ行を隣接させてから渡すと、正しくapple, banana, cherryになりました。Get-Uniqueを使うときは必ず事前にソートが必要です。並び順を保ちたいなら、ソートを伴わないSelect-Object -Uniqueを使うのが簡単です。
大文字小文字の扱い(SelectとSortで違う)
意外と見落としがちなのが大文字小文字の扱いです。Select-Object -UniqueとSort-Object -Uniqueで動きが違います。
$lines = "Apple", "apple", "APPLE" # Select-Object -Unique は大文字小文字を区別する → 3つとも残る $lines | Select-Object -Unique # → Apple, apple, APPLE # Sort-Object -Unique は大文字小文字を区別しない → 1つにまとまる $lines | Sort-Object -Unique # → APPLE(など1つだけ)
実機で確認したところ、Apple, apple, APPLEに対して、Select-Object -Uniqueは3つとも残し(大文字小文字を区別)、Sort-Object -Uniqueは1つにまとめました(大文字小文字を区別しない)。「重複を消したつもりが、大文字小文字違いが残ってしまった」というときはSelect-Object -Uniqueを、「大文字小文字を無視してまとめたい」ときはSort-Object -Uniqueを使い分けてください。なお、順序を保ちつつ大文字小文字を区別したいという場合はSelect-Object -Uniqueがそのまま使えます。逆に、順序を保ちつつ大文字小文字を無視したい、といった細かい制御が必要なときは、System.Collections.Generic.HashSetなどを使う方法もあります。
ファイルに書き戻す(エンコード注意)
重複を消した結果をファイルに保存するにはSet-Contentを使います。日本語を含む場合は-Encodingの指定を忘れないようにします。
# 重複行を削除して別ファイルに保存(順序保持)
Get-Content "C:\data\in.txt" |
Select-Object -Unique |
Set-Content "C:\data\out.txt" -Encoding UTF8
# 同じファイルに上書きしたい場合は、いったん変数に受けてから書く
#(パイプの途中で同じファイルを読み書きすると壊れることがあるため)
$lines = Get-Content "C:\data\list.txt" | Select-Object -Unique
$lines | Set-Content "C:\data\list.txt" -Encoding UTF8
実機では、5行(重複あり)のファイルをGet-Content | Select-Object -Unique | Set-Contentで処理し、3行のユニークなファイルに保存できることを確認しました。ただし注意点として、読み込みと書き込みを同じファイルに対してパイプで直接つなぐと、内容が壊れることがあります。Get-Content "list.txt" | ... | Set-Content "list.txt"のように同一ファイルを直接つなぐのは避け、いったん$lines = Get-Content ... | Select-Object -Uniqueで変数に受け取ってから書き込むと安全です。また、日本語を含むファイルでは-Encoding UTF8などを指定して、文字化けを防いでください。
主な方法まとめ
重複行を消す方法の違いをまとめます。
| 方法 | 並び順 | 大文字小文字 |
|---|---|---|
Select-Object -Unique |
出現順を保つ | 区別する |
Sort-Object -Unique |
ソートされる | 区別しない |
Sort-Object | Get-Unique |
ソートされる | 区別しない |
Get-Unique(単独) |
— | 隣接重複のみ(非推奨) |
よくある失敗
Get-Uniqueを単独で使う
隣接した重複しか消えません。必ずSort-Object | Get-Uniqueとするか、Select-Object -Uniqueを使います。
順序を保ちたいのにSort-Objectを使う
ソートで並び順が変わります。順序維持ならSelect-Object -Uniqueです。
大文字小文字違いが残る/消える
区別したいならSelect-Object -Unique、無視したいならSort-Object -Uniqueを選びます。
同じファイルにパイプで直接上書きする
内容が壊れることがあります。いったん変数に受けてから書き込みます。
書き戻しでエンコードを指定しない
日本語が文字化けします。Set-Content -Encoding UTF8などを指定します。
よくある質問
Get-Content ファイル | Select-Object -Uniqueを使います。最初に出てきた行を残し、2回目以降の同じ行を削除するため、元の出現順が保たれます。ログのように順番に意味があるデータに向いています。Get-Uniqueは隣り合った重複しか消さないためです。離れた位置の重複を消すには、先にSort-Objectで同じ行を隣接させる必要があります(Sort-Object | Get-Unique)。並び順を保ちたいなら、ソート不要のSelect-Object -Uniqueが簡単です。Select-Object -Uniqueは大文字小文字を区別するため、Appleとappleは別の行として両方残ります。Sort-Object -Uniqueは区別しないため、1つにまとまります。目的に応じて使い分けてください。$lines = Get-Content "list.txt" | Select-Object -Uniqueのように、いったん変数に受け取ってから$lines | Set-Content "list.txt" -Encoding UTF8で書き込むと安全です。Get-FileHashで各ファイルのハッシュを求め、同じハッシュのファイルをまとめる方法を別記事で解説しています。名前が違っても中身が同じファイルを検出できます。まとめ
- 順序を保つなら
Select-Object -Unique(大文字小文字を区別)。 - ソートしてよいなら
Sort-Object -Unique(大文字小文字を区別しない)。 Get-Uniqueは隣接重複のみ。使うならSort-Object | Get-Uniqueとします。- 同じファイルへの上書きは、いったん変数に受けてから行います。
- 書き戻しは
Set-Content -Encoding UTF8で文字化けを防ぎます。
重複行の削除は、「並び順を保つか」「大文字小文字を区別するか」で方法を選ぶのがコツです。とくにGet-Uniqueの「隣接重複しか消さない」という挙動は引っかかりやすいので、迷ったら順序を保てるSelect-Object -Uniqueを使うのがおすすめです。

