find_duplicate_lines.bat
İlk görülen satırların sırasını koruyarak yinelenen satır raporu ve temizlenmiş bir UTF-8 dosyası oluşturur.
Bul ve temizleBir TXT dosyasında yinelenen satırlar olup olmadığını denetleyin, tekrarları kaldırılmış temiz bir kopya oluşturun, özgün sıralamayı koruyun, UTF-8 kodlama sorunlarından kaçının veya elle denetim için PowerShell ve Komut İstemi’ni kullanın.
Yeniden kullanılabilir en kolay yöntem Yöntem 1’deki BAT betiğidir. Hem yinelenen satır raporu hem de tekrar içermeyen temiz bir kopya oluşturmak için bir TXT dosyasını betiğin üzerine sürükleyin. Özgün dosya değiştirilmez. Yalnızca konsolda hızlı denetim yapmak için aşağıdaki PowerShell komutunu kullanın:
Get-Content -LiteralPath ".\input.txt" -Encoding UTF8 |
Group-Object -CaseSensitive |
Where-Object Count -gt 1 |
Sort-Object Count -Descending |
Select-Object Count, Name
Değiştirin: input.txt ifadesini gerçek dosya adıyla değiştirin. Bu komut yalnızca yinelenen satırları bildirir; temizlenmiş bir dosya oluşturmaz. -Encoding UTF8 seçeneği Windows PowerShell 5.1’de önemlidir; aksi hâlde BOM içermeyen bir UTF-8 dosyası Windows ANSI kod sayfasıyla çözümlenebilir.
-CaseSensitive seçeneği Server ile server satırlarını farklı kabul eder. Büyük/küçük harf farkı yok sayılacaksa bu seçeneği kaldırın.
РіС...gibi metinler görünüyorsa dosya yanlış kodlamayla okunmuştur. UTF-8 dosyaları için -Encoding UTF8 seçeneğini kullanın. Eski bir ANSI dosyası için -Encoding Default veya UTF-16 little-endian metin için -Encoding Unicode seçeneğini kullanın.
İlk görülen satırların sırasını koruyarak yinelenen satır raporu ve temizlenmiş bir UTF-8 dosyası oluşturur.
Bul ve temizleHer yinelenen satırı ve kaç kez geçtiğini gösterir; ancak çok büyük dosyalarda yavaş olabilir.
Hızlı raporAynı satırları yan yana getirir, ancak yinelenenleri otomatik olarak bildirmez veya kaldırmaz.
Küçük dosyalarYinelenen satır, karşılaştırma değeri aynı dosyada birden fazla kez geçen satırdır. Ancak sonuç, seçtiğiniz karşılaştırma kurallarına bağlıdır.
| Satırlar | Tam karşılaştırma | Büyük/küçük harfe duyarsız karşılaştırma |
|---|---|---|
Windows ile Windows |
Yinelenen | Yinelenen |
Windows ile windows |
Farklı | Yinelenen |
example ile example |
Sondaki boşluk nedeniyle farklı | Boşluklar kırpılmadıkça yine farklı |
| İki boş satır | Yinelenen boş satır | Yinelenen boş satır |
Kesin bir denetim için büyük/küçük harfe duyarlı karşılaştırma kullanın ve boşlukları kırpmayın. Ad, URL, etki alanı veya tanımlayıcı listelerinde harf büyüklüğünü ve satır başı ya da sonundaki yanlışlıkla eklenmiş boşlukları yok saymayı tercih edebilirsiniz.
Tekrarlanan denetimler için aşağıdaki find_duplicate_lines.bat betiğini kullanın. Bir metin dosyasını betiğin üzerine sürükleyin veya tam yolu girin. Betik aynı klasörde iki UTF-8 dosyası oluşturur:
filename_duplicates.txt — yinelenen her satırı ve toplam görülme sayısını içeren rapor.filename_without_duplicates.txt — her satırın yalnızca ilk örneğinin tutulduğu temizlenmiş kopya.find_duplicate_lines.bat ifadesini dosya adı alanına girin.@echo off
setlocal EnableExtensions DisableDelayedExpansion
title Find and Remove Duplicate Lines in a Text File
set "INPUT_FILE=%~1"
if not defined INPUT_FILE (
echo Drag a text file onto this BAT file, or enter its full path below.
echo.
set /p "INPUT_FILE=Text file path: "
)
if not defined INPUT_FILE (
echo.
echo No file was selected.
pause
exit /b 1
)
for %%I in ("%INPUT_FILE%") do set "INPUT_FILE=%%~fI"
if not exist "%INPUT_FILE%" (
echo.
echo File not found:
echo %INPUT_FILE%
pause
exit /b 1
)
for %%I in ("%INPUT_FILE%") do (
set "DUPLICATE_FILE=%%~dpnI_duplicates.txt"
set "CLEAN_FILE=%%~dpnI_without_duplicates.txt"
)
echo.
echo Processing:
echo %INPUT_FILE%
echo.
set "FD_SCRIPT_FILE=%~f0"
set "FD_INPUT_FILE=%INPUT_FILE%"
set "FD_DUPLICATE_FILE=%DUPLICATE_FILE%"
set "FD_CLEAN_FILE=%CLEAN_FILE%"
powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "$content=[IO.File]::ReadAllText($env:FD_SCRIPT_FILE); $marker=':'+'POWERSHELL'; $code=$content.Substring($content.IndexOf($marker)+$marker.Length); & ([ScriptBlock]::Create($code)) -Path $env:FD_INPUT_FILE -DuplicatePath $env:FD_DUPLICATE_FILE -CleanPath $env:FD_CLEAN_FILE"
set "RESULT=%ERRORLEVEL%"
echo.
if "%RESULT%"=="0" (
echo Finished. Two files were created:
echo Duplicate report:
echo %DUPLICATE_FILE%
echo.
echo File without duplicate lines:
echo %CLEAN_FILE%
) else if "%RESULT%"=="2" (
echo Finished. No exact duplicate lines were found.
echo The cleaned copy was still created:
echo %CLEAN_FILE%
) else (
echo The file could not be processed.
)
echo.
pause
exit /b %RESULT%
:POWERSHELL
param(
[Parameter(Mandatory = $true)]
[string]$Path,
[Parameter(Mandatory = $true)]
[string]$DuplicatePath,
[Parameter(Mandatory = $true)]
[string]$CleanPath
)
$ErrorActionPreference = 'Stop'
function Get-TextEncodingInfo {
param([string]$FilePath)
$stream = [System.IO.File]::OpenRead($FilePath)
try {
$bom = New-Object byte[] 4
$read = $stream.Read($bom, 0, 4)
}
finally {
$stream.Dispose()
}
if ($read -ge 4 -and
$bom[0] -eq 0x00 -and $bom[1] -eq 0x00 -and
$bom[2] -eq 0xFE -and $bom[3] -eq 0xFF) {
return [PSCustomObject]@{
Encoding = [System.Text.Encoding]::GetEncoding(12001)
AllowAnsiFallback = $false
}
}
if ($read -ge 4 -and
$bom[0] -eq 0xFF -and $bom[1] -eq 0xFE -and
$bom[2] -eq 0x00 -and $bom[3] -eq 0x00) {
return [PSCustomObject]@{
Encoding = [System.Text.Encoding]::UTF32
AllowAnsiFallback = $false
}
}
if ($read -ge 3 -and
$bom[0] -eq 0xEF -and $bom[1] -eq 0xBB -and
$bom[2] -eq 0xBF) {
return [PSCustomObject]@{
Encoding = New-Object System.Text.UTF8Encoding($true)
AllowAnsiFallback = $false
}
}
if ($read -ge 2 -and $bom[0] -eq 0xFF -and $bom[1] -eq 0xFE) {
return [PSCustomObject]@{
Encoding = [System.Text.Encoding]::Unicode
AllowAnsiFallback = $false
}
}
if ($read -ge 2 -and $bom[0] -eq 0xFE -and $bom[1] -eq 0xFF) {
return [PSCustomObject]@{
Encoding = [System.Text.Encoding]::BigEndianUnicode
AllowAnsiFallback = $false
}
}
return [PSCustomObject]@{
Encoding = New-Object System.Text.UTF8Encoding($false, $true)
AllowAnsiFallback = $true
}
}
function Read-And-CleanTextFile {
param(
[string]$FilePath,
[System.Text.Encoding]$Encoding,
[string]$TemporaryCleanPath
)
$comparer = [System.StringComparer]::Ordinal
$counts = New-Object 'System.Collections.Generic.Dictionary[string,int]' ($comparer)
$seen = New-Object 'System.Collections.Generic.HashSet[string]' ($comparer)
$utf8WithBom = New-Object System.Text.UTF8Encoding($true)
$reader = New-Object System.IO.StreamReader($FilePath, $Encoding, $true)
$writer = New-Object System.IO.StreamWriter($TemporaryCleanPath, $false, $utf8WithBom)
$totalLines = 0
try {
while (($line = $reader.ReadLine()) -ne $null) {
$totalLines++
if ($seen.Add($line)) {
$writer.WriteLine($line)
}
$count = 0
if ($counts.TryGetValue($line, [ref]$count)) {
$counts[$line] = $count + 1
}
else {
$counts.Add($line, 1)
}
}
}
finally {
$reader.Dispose()
$writer.Dispose()
}
return [PSCustomObject]@{
Counts = $counts
TotalLines = $totalLines
UniqueLines = $seen.Count
}
}
$tempCleanPath = Join-Path ([System.IO.Path]::GetDirectoryName($CleanPath)) ([System.IO.Path]::GetRandomFileName())
try {
$encodingInfo = Get-TextEncodingInfo -FilePath $Path
try {
$data = Read-And-CleanTextFile -FilePath $Path -Encoding $encodingInfo.Encoding -TemporaryCleanPath $tempCleanPath
}
catch [System.Text.DecoderFallbackException] {
if (-not $encodingInfo.AllowAnsiFallback) {
throw
}
if (Test-Path -LiteralPath $tempCleanPath) {
Remove-Item -LiteralPath $tempCleanPath -Force
}
$data = Read-And-CleanTextFile -FilePath $Path -Encoding ([System.Text.Encoding]::Default) -TemporaryCleanPath $tempCleanPath
}
if (Test-Path -LiteralPath $CleanPath) {
Remove-Item -LiteralPath $CleanPath -Force
}
Move-Item -LiteralPath $tempCleanPath -Destination $CleanPath
$duplicates = @(
$data.Counts.GetEnumerator() |
Where-Object { $_.Value -gt 1 } |
Sort-Object Key
)
if ($duplicates.Count -eq 0) {
if (Test-Path -LiteralPath $DuplicatePath) {
Remove-Item -LiteralPath $DuplicatePath -Force
}
Write-Host ("Lines read: {0}" -f $data.TotalLines)
Write-Host ("Unique lines written: {0}" -f $data.UniqueLines)
exit 2
}
$report = New-Object System.Collections.Generic.List[string]
$report.Add("Count`tLine")
foreach ($duplicate in $duplicates) {
$report.Add(("{0}`t{1}" -f $duplicate.Value, $duplicate.Key))
}
$utf8WithBom = New-Object System.Text.UTF8Encoding($true)
[System.IO.File]::WriteAllLines($DuplicatePath, $report, $utf8WithBom)
Write-Host ("Lines read: {0}" -f $data.TotalLines)
Write-Host ("Unique lines written: {0}" -f $data.UniqueLines)
Write-Host ("Duplicate groups found: {0}" -f $duplicates.Count)
exit 0
}
catch {
if (Test-Path -LiteralPath $tempCleanPath) {
Remove-Item -LiteralPath $tempCleanPath -Force
}
Write-Error $_.Exception.Message
exit 1
}
find_duplicate_lines.batdosyasının üzerine sürükleyin. Alternatif olarak BAT dosyasına çift tıklayın ve metin dosyasının tam yolunu yapıştırın.filename_duplicates.txt dosyasını açarak yinelenen satırları ve görülme sayılarını görüntüleyin.filename_without_duplicates.txt dosyasını açarak yinelenen örnekleri kaldırılmış temiz listeyi alın.| Dosya | Sıralama davranışı | İçerik |
|---|---|---|
filename_duplicates.txt |
Yinelenen satıra göre alfabetik sıralanır | Her yinelenen değer için toplam sayısıyla birlikte tek kayıt |
filename_without_duplicates.txt |
Sıralanmaz; özgün sıra korunur | Her tam satırın yalnızca ilk örneği |
| Özgün TXT dosyası | Sıralanmaz veya değiştirilmez | Değişmeden kalır |
Count Line
4 example.com
2 server-01
Windows ile windows farklı satırlar olarak değerlendirilir.PowerShell dosyayı bir satır koleksiyonu olarak okur. -Encoding UTF8 Windows PowerShell 5.1’e, BOM içermeyen UTF-8 dosyaları da dâhil olmak üzere UTF-8 dosyasını doğru çözümlemesini söyler. Group-Object aynı satırları gruplar ve Where-Object yalnızca birden fazla öğe içeren grupları tutar.
powershellyazın ve Girin:.input.txt ifadesini dosya adınızla değiştirdikten sonra komutu çalıştırın.Get-Content -LiteralPath ".\input.txt" -Encoding UTF8 |
Group-Object -CaseSensitive |
Where-Object Count -gt 1 |
Sort-Object Count -Descending |
Select-Object Count, Name
Count Name
----- ----
4 example.com
3 192.168.1.10
2 Windows 11
Bu sonuç, example.com satırının dört kez, 192.168.1.10 satırının üç kez ve Windows 11 satırının iki kez geçtiği anlamına gelir.
Tam yolu belirterek aynı denetimi herhangi bir klasörden çalıştırabilirsiniz:
Get-Content -LiteralPath "C:\Users\User\Desktop\input.txt" -Encoding UTF8 |
Group-Object -CaseSensitive |
Where-Object Count -gt 1 |
Select-Object Count, Name
-LiteralPath dosya adında köşeli parantez gibi karakterler bulunduğunda tercih edilir; çünkü PowerShell yolu yazıldığı biçimde işler. Örneklerde -Encoding UTF8kullanılmıştır; kaynak dosya UTF-8 değilse bunu doğru kodlama parametresiyle değiştirin.
Yalnızca en az bir yinelenen satır bulunup bulunmadığını öğrenmeniz gerekiyorsa bu sürümü kullanın:
$duplicate = Get-Content -LiteralPath ".\input.txt" -Encoding UTF8 |
Group-Object -CaseSensitive |
Where-Object Count -gt 1 |
Select-Object -First 1
if ($null -ne $duplicate) {
Write-Host "Duplicate lines found."
} else {
Write-Host "No duplicate lines found."
}
Komut yalnızca ilk yinelenen grubu döndürür; ancak PowerShell sonucu üretmeden önce yine de dosyayı okuyup gruplamak zorundadır. Betiklerde, zamanlanmış görevlerde veya tekrarlanabilir doğrulama iş akışlarında kullanışlıdır.
if (Get-Content -LiteralPath ".\input.txt" -Encoding UTF8 | Group-Object -CaseSensitive | Where-Object Count -gt 1 | Select-Object -First 1) { "Duplicate lines found" } else { "No duplicate lines found" }
Yinelenen satır raporunu yalnızca konsolda görüntülemek yerine kaydetmek için gruplanmış sonuçları bir CSV dosyasına aktarın:
Get-Content -LiteralPath ".\input.txt" -Encoding UTF8 |
Group-Object -CaseSensitive |
Where-Object Count -gt 1 |
Sort-Object Count -Descending |
Select-Object Count, @{Name="Line"; Expression={$_.Name}} |
Export-Csv -LiteralPath ".\duplicate-report.csv" -NoTypeInformation -Encoding UTF8
Çıktı dosyası duplicate-report.csv Excel, LibreOffice Calc, Not Defteri veya başka bir metin düzenleyicisinde açılabilir.
Yinelenen her satırın tek kopyasını içeren düz bir TXT dosyasına ihtiyacınız olduğunda aşağıdaki komutu kullanın:
Get-Content -LiteralPath ".\input.txt" -Encoding UTF8 |
Group-Object -CaseSensitive |
Where-Object Count -gt 1 |
ForEach-Object Name |
Set-Content -LiteralPath ".\duplicate-lines.txt" -Encoding UTF8
Set-Content ile kullanmayın.
Group-Object varsayılan olarak büyük/küçük harfe duyarsızdır. -CaseSensitive seçeneğini kaldırarak PC Pcve pc değerlerini aynı kabul edin:
Get-Content -LiteralPath ".\input.txt" -Encoding UTF8 |
Group-Object |
Where-Object Count -gt 1 |
Select-Object Count, Name
Get-Content -LiteralPath ".\input.txt" -Encoding UTF8 |
ForEach-Object { $_.Trim() } |
Group-Object -CaseSensitive |
Where-Object Count -gt 1 |
Select-Object Count, Name
Bu işlem example exampleve example değerlerini eşdeğer yapar. Satır içindeki boşlukları kaldırmaz.
Get-Content -LiteralPath ".\input.txt" -Encoding UTF8 |
Where-Object { $_.Trim().Length -gt 0 } |
Group-Object -CaseSensitive |
Where-Object Count -gt 1 |
Select-Object Count, Name
Get-Content -LiteralPath ".\input.txt" -Encoding UTF8 |
ForEach-Object { $_.Trim() } |
Where-Object { $_.Length -gt 0 } |
Group-Object |
Where-Object Count -gt 1 |
Sort-Object Count -Descending |
Select-Object Count, Name
Yerleşik Windows sort.exe komutu aynı satırları yan yana sıralayabilir. Bu, yinelenen satırları elle görmeyi kolaylaştırır; ancak SORT yinelenen satırları otomatik olarak tanımlamaz, saymaz veya kaldırmaz.
cmdyazın ve Girin:.sort "input.txt" /o "sorted.txt"
Açın: sorted.txt dosyasını Not Defteri’nde açın. Yinelenen değerler yan yana görünür ve görsel denetim yapılabilir.
Komut İstemi’nden otomatik denetim yapmak için CMD içinden Windows PowerShell’i çağırın. Bu örnekte ayrıca UTF-8 açıkça belirtilir; böylece Kiril ve aksanlı karakterler Windows PowerShell 5.1’de ANSI olarak çözümlenmez:
powershell.exe -NoProfile -Command "Get-Content -LiteralPath '.\input.txt' -Encoding UTF8 | Group-Object -CaseSensitive | Where-Object Count -gt 1 | Select-Object Count, Name"
Yöntem 1’deki BAT betiği, kısa Group-Object örneklerinden daha verimlidir; çünkü dosyanın tamamını bir diziye okumaz ve her kaynak satırı alfabetik olarak sıralamaz. Dosyayı sırayla okur, ilk örnekleri doğrudan temizlenmiş çıktıya yazar ve bellekte yalnızca benzersiz anahtarlarla sayaçlarını tutar.
Doğrudan PowerShell komutları kullanışlıdır; ancak Group-Object büyük dosyalarda belirgin biçimde daha yavaş olabilir ve önemli miktarda RAM kullanabilir.
Büyük dosyalarda şu önlemleri alın:
Group-Object.PowerShell Kiril, aksanlı veya İngilizce dışındaki metinleri РіС...gibi diziler olarak gösteriyorsa kaynak dosya genellikle yanlış karakter kodlamasıyla çözümleniyordur. Metnin kendisi bozulmamış olabilir; sorun Get-Content komutunun dosya baytlarını nasıl yorumladığıdır.
-Encoding UTF8.
Get-Content -LiteralPath ".\input.txt" -Encoding UTF8 |
Group-Object -CaseSensitive |
Where-Object Count -gt 1 |
Sort-Object Count -Descending |
Select-Object Count, Name
Bu yöntem Windows PowerShell 5.1’de BOM içeren veya içermeyen UTF-8 metinlerde çalışır. Yeni PowerShell sürümlerinde birçok metin işlemi için UTF-8 genellikle varsayılandır; ancak bunu açıkça belirtmek komutu belirsizlikten kurtarır.
| Kaynak dosya kodlaması | Get-Content parametresi | Ne zaman kullanılmalı? |
|---|---|---|
| UTF-8 | -Encoding UTF8 |
BOM içermeyen UTF-8 dâhil modern TXT dosyaları için önerilir. |
| Windows ANSI kod sayfası | -Encoding Default |
Geçerli Windows sistem kod sayfasıyla kaydedilmiş eski dosyalar için kullanın. |
| UTF-16 little-endian | -Encoding Unicode |
Genellikle FF FE BOM’u ile tanımlanan UTF-16 LE dosyaları için kullanın. |
| UTF-16 big-endian | -Encoding BigEndianUnicode |
Genellikle FE FF BOM’u ile tanımlanan UTF-16 LE dosyaları için kullanın. |
Get-Content -LiteralPath ".\input.txt" -Encoding Default |
Group-Object -CaseSensitive |
Where-Object Count -gt 1 |
Select-Object Count, Name
Get-Content -LiteralPath ".\input.txt" -Encoding Unicode |
Group-Object -CaseSensitive |
Where-Object Count -gt 1 |
Select-Object Count, Name
chcp 65001 konsol kod sayfasını değiştirir; ancak Get-Content komutuna kaynak dosyanın nasıl çözümleneceğini bildirmez. -Encoding UTF8 seçeneğini Get-Content üzerinde kullanın.
Bu rehberde yer alan yeniden kullanılabilir find_duplicate_lines.bat betiği BOM içeren veya içermeyen UTF-8’i algılar, BOM işaretli UTF-16 ve UTF-32’yi destekler ve BOM’suz bayt dizisi geçerli UTF-8 değilse Windows ANSI kod sayfasına geri döner. Hem yinelenen satır raporunu hem de temizlenmiş kopyayı BOM’lu UTF-8 olarak yazar.
Get-Content Group-Objectve Select-Object tabanlı komutlar, açıkça Set-Content veya Export-Csv.(Get-Content -LiteralPath ".\input.txt" -Encoding UTF8).Count. Çok büyük dosyalarda bu işlem yine de dosyayı PowerShell üzerinden okur ve zaman alabilir.find_duplicate_lines.batotomatik olarak *_without_duplicates.txt dosyasını oluşturur ve kaynak dosyayı değiştirmez. Temizlenmiş çıktı her tam satırın ilk örneğini tutar.Group-Object varsayılan olarak büyük/küçük harfe duyarsızdır. Büyük ve küçük harflerin tam olarak karşılaştırılması gerekiyorsa -CaseSensitive seçeneğini ekleyin.-Encoding UTF8 seçeneğini ekleyin. Konsolu yalnızca chcp 65001 ile değiştirmek Get-Content komutunun dosyayı çözümleme biçimini düzeltmez.find_duplicate_lines.bat seçilen dosyayı okur ve *_duplicates.txt ile *_without_duplicates.txtdosyalarını oluşturur. Özgün metin dosyasının üzerine hiçbir zaman yazılmaz.Tekrarlanan denetimler için find_duplicate_lines.batkullanın. Dosyayı sürükle ve bırak ile kabul eder, büyük/küçük harfe duyarlı tam karşılaştırma yapar, alfabetik olarak sıralanmış bir yinelenen satır raporu oluşturur ve özgün sırayı koruyarak yinelenen örnekleri içermeyen ikinci bir UTF-8 dosyası yazar.
Yalnızca etkileşimli bir rapora ihtiyaç duyduğunuzda veya karşılaştırma kurallarını özelleştirmek istediğinizde PowerShell’i Get-Content -Encoding UTF8 ile Group-Object ile kullanın. Windows sort.exe komutu yalnızca küçük dosyaların elle incelenmesi için uygundur.