alfabravo
Goto Top

Mit Batchdatei aus einer .txt alle doppelten Zeilen (Duplikate) komplett löschen

Hallo Admins,

ich müsste mittels Batchdatei (!) folgendes Problem lösen:

Eine Textdatei Daten.txt hat folgenden Inhalt:

11111111
22222222
33333333
44444444
55555555
55555555
22222222

Nun sollen alle Zeilen, die doppelt vorkommen, KOMPLETT gelöscht werden - oder alternativ: alle Zeilen, die einmal vorkommen, in eine neue Datei geschrieben werden. Das Ergebnis soll jedenfalls so aussehen:


11111111
33333333
44444444


Mit folgendem Code werden zumindest alle Duplikate gelöscht:

@echo off & setlocal
set "Datei=Daten.txt"
set "Bak=.bak"
set /a LineNo=0

move "%Datei%" "%Datei%%Bak%"
copy nul "%Datei%">nul
for /f "usebackq delims=" %%i in ("%Datei%%Bak%") do set "Zeile=%%i" & call :ProcessLine
del "%Datei%%Bak%"
goto :eof

:ProcessLine
set /a LineNo+=1
echo Validiere Zeile %LineNo% ...
findstr /b /c:"%Zeile:~,8%" "%Datei%">nul || >>"%Datei%" echo %Zeile%
goto :eof

Doch das Ergebnis sieht so aus:

11111111
22222222
33333333
44444444
55555555

Das war allerdings nicht das was ich erreichen wollte, siehe oben.

Hat jemand eine Idee für dieses knifflige Problem? Ich komme da nicht so recht weiter ... Und wie gesagt, es müsste mittels Batchdatei laufen.

Vielen Dank & Gruß

Content-ID: 116968

Url: https://administrator.de/contentid/116968

Ausgedruckt am: 22.11.2024 um 22:11 Uhr

bastla
bastla 27.05.2009 um 21:29:07 Uhr
Goto Top
Hallo alfabravo und willkommen im Forum!

Du könntest es mit einem zweiten Durchlauf versuchen - im Prinzip etwa so:
@echo off & setlocal 
set "Datei=Daten.txt"  
set "Bak=.bak"  
set "TempDatei=%temp%\TempDatei.txt"  
set "Duplikate=%temp%\Duplikate.txt"  
set /a LineNo=0 

move "%Datei%" "%Datei%%Bak%"  
copy nul "%Duplikate%">nul  
copy nul "%TempDatei%">nul  

for /f "usebackq delims=" %%i in ("%Datei%%Bak%") do set "Zeile=%%i" & call :ProcessLine  
for /f "usebackq delims=" %%i in ("%TempDatei%") do set "Zeile=%%i" & call :ProcessLine2  

del "%Datei%%Bak%"   
del "%Duplikate%"  
del "%TempDatei%"  
goto :eof 

:ProcessLine 
set /a LineNo+=1 
echo Validiere Zeile %LineNo% ... 
findstr /b /c:"%Zeile:~,8%" "%TempDatei%">nul && >>"%Duplikate%" echo %Zeile% || >>"%TempDatei%" echo %Zeile%  
goto :eof

:ProcessLine2 
findstr /b /c:"%Zeile:~,8%" "%Duplikate%">nul || >>"%Datei%" echo %Zeile%  
goto :eof
Grüße
bastla
alfabravo
alfabravo 27.05.2009 um 22:29:28 Uhr
Goto Top
Hallo bastla,

Deine Lösung ist perfekt, genau das habe ich gesucht. Vielen Dank !!!

Gruß, alfabravo
77559
77559 27.05.2009 um 22:50:43 Uhr
Goto Top
Hallo bastla,

der findstr /V /G:datei wird doch immer wieder unterschätzt face-wink

:: RemoveDupes.cmd :::::::::::::::::::::::::::::::::::::::::::::::::
@echo off & setlocal EnableDelayedExpansion
set "Datei=test.txt"  
set "Bak=.bak"  
set "Duplikate=%temp%\Duplikate.txt"  
move "%Datei%" "%Datei%%Bak%"  
copy nul "%Duplikate%">nul  
If defined LastLine Set "LastLine="  

for /f "delims=" %%A in ('Sort ^<"%Datei%%Bak%" ') do (  
  If /i "!LastLine!"=="%%A" (Echo/%%A)>>"%Duplikate%"  
  set "LastLine=%%A"  
)
findstr /V /G:"%Duplikate%" <"%Datei%%Bak%" >"%Datei%"  
del "%Duplikate%"   

Gruß
LotPings
bastla
bastla 27.05.2009 um 23:02:02 Uhr
Goto Top
@77559
der findstr /V /G:datei wird doch immer wieder unterschätzt face-wink
Mitnichten - hatte es (allerdings ohne Umleitung für die Eingabe, sondern mit direkter Angabe) versucht und weiß noch immer nicht, warum es nicht so wie ich wollte - deshalb die weniger elegante, aber immerhin funktionierende Version ...

Grüße
bastla
Biber
Biber 28.05.2009 um 08:29:59 Uhr
Goto Top
Moin LotPings,

da hätte ich aber noch einen Verbesserungsvorschlag....

In (mindestens) zwei Fällen wird sich der Starter Deines Schnipsels eventuell ein kleines bisschen ärgern:
  • wenn eine Zeile in der Textdatei enthalten ist, die der FindStr.exe irgendwie zu lang zum Suchen erscheint (führt zu Fehler: "FINDSTR: Suchzeichenfolge zu lang.")
  • oder, viel wahrscheinlicher: es gibt nun gar keine Duplikate in der Originaldatei. (Führt zu Fehler: "FINDSTR: Keine Suchzeichenfolge")

In diesen beiden und allen anderen Fällen, in denen FindStr abgrätscht hinterlässt der obige Batch eine Fehlermeldung auf dem Bildschirm und eine Originaldatei (bzw. Datei mit dem Namen der Originaldatei) in der Größe von 0 Byte.

Deshalb würde ich noch eine minimale Fehlerbehandlung einbauen:
:: RemoveDups.cmd :::::::::::::::::::::::::::::::::::::::::::::::::
@echo off & setlocal EnableDelayedExpansion
set "Datei=duptest.txt"  
set "Bak=.bak"  
set "Duplikate=%temp%\Duplikate.txt"  
move "%Datei%" "%Datei%%Bak%"  
copy nul "%Duplikate%">nul  
If defined LastLine Set "LastLine="  

for /f "delims=" %%A in ('Sort ^<"%Datei%%Bak%" ') do (  
  If /i "!LastLine!"=="%%A" (Echo/%%A)>>"%Duplikate%"  
  set "LastLine=%%A"  
)
findstr /V /G:"%Duplikate%" <"%Datei%%Bak%" >"%Datei%"  
if errorlevel 1 (
    Echo Fehler aufgetreten - Originaldatei wird wiederhergestellt.
    dir "%datei%"|find /i "%datei%" & type "%datei%" & pause  
    move "%Datei%%Bak%" "%Datei%"  
)    
del "%Duplikate%"   

Der Kurztest am CMD-Prompt.
>type duptest.txt
11111111
33333333
44444444

>e:\schnipsel\RemoveDups.cmd
FINDSTR: Keine Suchzeichenfolge
Fehler aufgetreten - Originaldatei wird wiederhergestellt.
28.05.09  08:27                 0 duptest.txt
Drücken Sie eine beliebige Taste . . .

>dir duptest.txt|find "duptest"  
28.05.09  08:15                30 duptest.txt

Grüße
Biber
77559
77559 28.05.2009 um 11:01:26 Uhr
Goto Top
Zitat von @Biber:
da hätte ich aber noch einen Verbesserungsvorschlag....
Immer gerne gesehen face-wink

Eine Umkehrung der Logik sscheint mir aber sinnvoller,
die neue Datei ersetzt nur dann die alte wenn kein Fehler aufgetreten ist.
Extra ein bisschen kryptischer und kürzer aber auch komfortabler.
:: RemoveDupes.cmd :::::::::::::::::::::::::::::::::::::::::::::::::
@cls&echo off&setlocal EnableDelayedExpansion
if Not Exist \"%~1\" (Echo Usage: %~nx0 Dubletten.txt&Pause&Exit /b 0)  
(copy nul \"%~f1.Dup%\">nul)&set cnt=0&If defined LL Set \"LL=\"  
for /f \"delims=\" %%A in (\'Sort ^<\"%~f1\" \') do (  
If /i \"!LL!\"==\"%%A\" (Echo/%%A)>>\"%~f1.Dup\"  
set \"LL=%%A\"&Set /A cnt+=1)  
IF %cnt% GTR 0 findstr /V /G:\"%~f1.Dup\" <\"%~f1\" >\"%~f1.new\"&&(Move /Y \"%~f1.new\" \"%~f1\">NUL)||Echo Fehler! %~f0 unverändert  
For %%A in (new Dup) do del \"%~f1.%%A\" >NUL 2>&1  

Gruß
LotPings