Das ist gar nicht mal so trivial.
Du gehst zeilenweise durch, d.h. um den Anteil der bisher betrachteteten Zeilen zu berechnen musst du wissen wie viele Zeilen insgesamt da sind. Dafür musst du einmal über die Datei laufen und nix machen außer die Zeilen zählen.
Dann wenn du beim vergleichen durch die zeilen läufst kannst du einfach einen counter mitlaufen lassen, und dann den anzeil berechnen (curr / all) und dann entsprechend einen progress anzeigen.
Mal ganz davon abgesehen sollte das aber auf gar keinen fall so lange dauern das du eine Progressbar brauchen solltest.
Beispiel, dieses Python script macht genau das was dein Script macht (also removed alle dublicates von einer eingabe):
Code:
import sys
lines = set()
for ln in sys.stdin:
ln = ln.rstrip()
if ln not in lines:
print(ln)
lines.add(ln)
und braucht für den gesammten LLVM source code (150 mb, c.a. 4 mio lines) wenige sekunden.
Dein script habe ich auf dem selben Source nach c.a. 20 minuten abgebrochen.
Der Hauptgrund dafür ist ziemlich simpel, Asymptotische Laufzeit. Wie dein Script läuft meins auch Zeilenweise drüber, der Unterschied ist aber wie der inhalt verglichen wird. Ich benutze ein Python-Set, was unterliegend ein HashSet benutzt und damit eine Average-Case lookup und insertion zeit hat von 1, im worst case N (größe des Sets) aber der worst case tritt extrem selten ein. Wenn die datei also N zeilen hat ist der durchschnittliche aufwand N*1.
Dein script schreibt alle gefunden zeilen in die Ausgabe datei, und macht dann eine lineare Suche drüber. Die Asymptotische laufzeit ist also im Best Case 1 (wenn es direkt die erste zeile Matcht) im Worst case N (wenn die zeile nicht vorkommt muss jede Zeile überprüft werden). Der Average case ist nicht so klar, wenn die datei die du untersuchst nur sehr wenige dublikate hat, dann ist der Average Case N, weil für jedes nicht-dublikat (was fast alle zeilen sind) musst du alle N zeilen durchlaufen. Wenn insgesammt nur 3-4 verschiedene Werte aber vorkommen und fast alles ein dublikat ist ist es genau anders rum und der Average Case ist 1.
Solang aber die anzahl an nicht dublikaten nicht extrem viel kleiner ist als die Anzahl an Dublikaten (also größenordnungen niedriger), ist der Average Case Linear also N und damit die Gesammtlaufzeit N*N = N².
Setzen wir die Zahlen einfach mal für mein LLVM ein: Mein Script: Linear bei 4 mio zeilen = 4 mio überprüfungen
Dein script Quadratisch: 4mio*4mio = 1.6e+13 (16 mit 12 mal 0 hintendran) also 16 Billionen (Deutsche billionen, englische Trillion) überprüfungen.
Noch dazu kommt, das Python script hat alle daten im RAM, dein script schreibt zu erst die zeile die gesucht wird in eine datei, um danach die zeile in einer anderen datei zu suchen. Es werden also 3 Platten operationen (1xschreiben, 2xLesen) ausgeführt.
Hashsets haben eine beschissene Konstante laufzeit, verglichen mit anderen Datenstrukturen, ist aber bestimmt trozdem um so einen Faktor 10-100 schneller als eine Plattenoperation. D.h. Du führst nicht nur 4 millionen mal so viele Operationen aus wie mein script, jede deiner Operationen ist auch noch 10 bis 100 mal so langsam.
Eine alternative wäre die verwendung einer Sortierten Liste, z.b. über einen RBT (Red-Black-Tree), auf der man dann binärsuche machen kann. Die Worst-Case laufzeit hierbei ist Log2(n), wodurch die gesammt anzahl an vergleichen bei dem LLVM source also bei c.a. 90 mio vergleichen läg, was immernoch massenhaft besser ist als dein linearer ansatz. Das hat den vorteil gegenüber HashSets, das der Konstante overhead geringer ist als beim Pflegen einer HashTable. Damit wäre das auch eine möglichkeit.
Langer Rede kurzer Sinn: statt eine Progressbar einzubauen die dir anzeigt wie lang es dauert, bau doch einfach das Script so das es gar nicht erst so lange dauert.
Ich kann dir jetzt nicht sagen wie das in Batch geht, ich würde dir aber auch empfehlen einfach nicht Batch zu verwenden. Für alles was nicht das simple aufrufen von Programmen ist ist Batch gänzlich ungeeignet. Mein python script oben ist 1. Besser, 2. Kürzer und 3. Leserlicher als jedes Batch script mit dem du ankommen köntest. Wenn du nicht garantieren kannst/möchtest das python vorinstalliert ist, dieses C++ Programm kannst du einfach für Windows Compilen und nutzt auch ein HashSet:
Code:
#include<unordered_set>
#include<iostream>
#include<string>
int main() {
std::unordered_set<std::string> lines;
std::string line;
while (std::getline(std::cin, line)) {
if (!lines.count(line)) {
lines.insert(line);
std::cout << line << '\n';
}
}
return 0;
}