[Erledigt] Dateien zählen

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
charlytango
Beiträge: 843
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

[Erledigt] Dateien zählen

Beitrag von charlytango »

Hi.

Es sollen ausgehend von einem Verzeichnis alle Dateien unter diesem Verzeichnis bearbeitet werden.
Alles ok -- mit FindFirst, FindNext und Konsorten geht das ganz gut.

Mir geht es aber um die Rückmeldung an den Benutzer in der Art von

Bearbeite x von 20000

wobei das X ja kein Problem ist.

Meine Frage: Muss ich den Verzeichnisbaum zweimal durhsuchen? Also einmal um die Dateien zu zählen und ein zweites mal um sie zu bearbeiten?
Oder gibt es eine elegantere/schnellere Methode die Gesamtzahl der zu bearbeitenden Dateien zu ermitteln?

THX
Zuletzt geändert von charlytango am Fr 12. Mär 2021, 13:47, insgesamt 1-mal geändert.

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Dateien zählen

Beitrag von Winni »

Hi!

Also: Solange Du nicht auf die Idee kommst, die Dateien umzubenennen ist das einfach.


Du klaust das Beispiel aus der fpc documentation https://www.freepascal.org/docs-html/rt ... first.html und baust das um:


Code: Alles auswählen

Uses .......,SysUtils;
Procedure Example43;

Var Info : TSearchRec;
    Count : Longint;
    s : string;
Begin
  Count:=0;
  If FindFirst ('*',faAnyFile,Info)=0 then
    begin
    Repeat
      Inc(Count);
      With Info do
        begin
       s := IntToStr(Count) + #32;
        If (Attr and faDirectory) = faDirectory then
        s := s+ 'Dir:  ';
        s := s + name +#32+IntToStr(size);
       ListBox1.Items.add(s);  
       ListBox1.TopItem := ListBox1.Count - 10;
       application.ProcessMessages;
       s:= '';
       FileBearbeiten(name); // <== Hier kommst Du
        end;
    Until FindNext(info)<>0;
    FindClose(Info);
    end;
  showMessage ('Finished search. Found ' +IntToStr(Count),' matches');
End;


Für das Beispiel brachst Du dann noch ne ListBox auf Deinem Formular.
Das war's!

Winni

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1432
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Dateien zählen

Beitrag von fliegermichl »

Ich schätze du musst wirklich zweimal durch.
Aber einfach nur die Dateien ermitteln und zählen geht recht pronto, da diese ja nicht geöffnet werden müssen.
Rekursive Lösung

Code: Alles auswählen

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, EditBtn, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    DirectoryEdit1: TDirectoryEdit;
    lbDirs: TLabel;
    lbFiles: TLabel;
    procedure Button1Click(Sender: TObject);
  private

  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var dirs, files : integer;
    start : int64;

  procedure CountFiles(path : string; var dirs, files : integer);
  var sr : TSearchRec;
       i : integer;
  begin
    i := FindFirst(path + DirectorySeparator + AllFilesMask, faAnyFile, sr);
    while (i = 0) do
    begin
      if (sr.name <> '.') and (sr.Name <> '..') then
      begin
        if (sr.Attr and faDirectory <> 0) then
        begin
          inc(dirs);
          CountFiles(path + DirectorySeparator + sr.Name, dirs, files);
        end else
        begin
          inc(files);
        end;
      end;
      i := FindNext(sr);
    end;
    FindClose(sr);
  end;

begin
 Start := GetTickCount64;
 dirs := 0;
 files := 0;
 CountFiles(DirectoryEdit1.Directory, dirs, files);
 lbDirs.Caption := dirs.toString;
 lbFiles.Caption := files.toString;
 ShowMessage(Format('needed %d Ticks', [GetTickCount64 - start]));
end;

end.
hat bei mir für ein komplettes Lazarus Verzeichnis 484 Ticks benötigt.

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Dateien zählen

Beitrag von Winni »

@fliegermichl

Ich hatte sein Problem nicht derart verstanden, dass er den gesamten file tree braucht, sondern eher so, wie er pro Datei eine Rückmeldung bekommt.

Aber das müsste er eklären.

Winni

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1432
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Dateien zählen

Beitrag von fliegermichl »

@winni

Die Frage war doch eigentlich recht eindeutig.
Er möchte eine Meldung anzeigen "Bearbeite Datei x von y".
x war klar, y fehlte. Also muss er zuerst die Anzahl der zu bearbeitenden Dateien ermitteln.

Gruß
Michael

charlytango
Beiträge: 843
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: Dateien zählen

Beitrag von charlytango »

@winni
@fliegermichl

erstmal danke bisher.

Es ging tatsächlich NUR um das Zählen der Dateien und die Laufzeitoptimierung dieser Aktion.
Und natürlich soll der Wert auch stimmen damit man bei der eigentlichen Bearbeitung der Dateien sauber runter zählen kann.

mp3tag - ein Programm zur Bearbeitung von diversesten Tags in Multimediadateien verwendet z.B. so etwas.
Ich war nur immer erstaunt von dem Tempo in dem die Meldung "bearbeite X von 6728" kommt.
Irgendwoher muss die Gesamtzahl der Dateien ja kommen und das noch dazu praktisch gleich nach dem entsprechenden Tastendruck. Jedenfalls sauschnell.

Als Info nehme ich mal mit dass ich da zweimal drüber muss -- sofern nicht noch jemand etwas besseres einfällt ;)

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Dateien zählen

Beitrag von Winni »

@fliegermichl

Okay. Hast gewonnen. Hab ich zu diagonal gelesen.
Das gibt es streng genommen nur eine 2-Pass-Lösung.

Es sei denn, man orientiert sich an den undurchsichtigen Algorithmen von Download-Zeiten.
Oder der "Estimated Time" bei Kopier-Orgien auf externe Festplatten.
Die EST fängt erstmal bei 200 Stunden an. Springt dann auf 2. Und dann wird der timespan immer kleiner.

Oder irgendwelche BitTorrent software, die alles nach dem letzten Durchsatz berechnet. Und dann immer abwechseln eine Restzeit zwischen 5 Minuten und 2 Stunden präsentiert.
Nach dem Motto: Hauptsache der User sieht was.

Da nehmen wir doch einfach mal an, dass durchnittlich 200 Dateien pro Verzeichnis vorhanden sind. Und dann .... Hauptsache der User sieht was.....

Winni

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Dateien zählen

Beitrag von Winni »

charlytango hat geschrieben:
Do 11. Mär 2021, 21:59

Ich war nur immer erstaunt von dem Tempo in dem die Meldung "bearbeite X von 6728" kommt.
Irgendwoher muss die Gesamtzahl der Dateien ja kommen und das noch dazu praktisch gleich nach dem entsprechenden Tastendruck. Jedenfalls sauschnell.

Als Info nehme ich mal mit dass ich da zweimal drüber muss -- sofern nicht noch jemand etwas besseres einfällt ;)
Hi!

Der Trick ist, dass einige Software schon mal "heimlich" Buch führt über die Anzahl der Dateien oder sogar den Inhalt ganzer Vereichnisse. Die Starten bevor Du die erste Taste gedrückt hast schon mal ein paar Threads - was die Hardware so hergibt - im Hintergrund und die durchforstet alle in Frage kommende Verzeichnisse. Und die hast Du ja entweder in den Einstellungen hinterlassen oder er weiss es von der letzten Session. Und Du wunderst Dich, dass das Biest soviel Speicher benötigt ...

Winni

Benutzeravatar
theo
Beiträge: 10468
Registriert: Mo 11. Sep 2006, 19:01

Re: Dateien zählen

Beitrag von theo »

Wenn man wirklich mit lange andauernder Zählerei rechnen muss, könnte man auch beim Bearbeitungsstart gleichzeitig einen separaten Thread starten welcher das Zählen übernimmt.
Anfänglich würde man dann nur ein Lebenszeichen anzeigen, wie z.B. die Zahl der bearbeiteten Dateien (x) und sobald der Thread fertig ist, könnte man die Anzeige auf x-von-y oder Prozent umschalten.
So würde ich das vielleicht machen, damit die Bearbeitung gleich los geht.

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Dateien zählen

Beitrag von Winni »

charlytango hat geschrieben:
Do 11. Mär 2021, 21:59

Ich war nur immer erstaunt von dem Tempo in dem die Meldung "bearbeite X von 6728" kommt.
Irgendwoher muss die Gesamtzahl der Dateien ja kommen und das noch dazu praktisch gleich nach dem entsprechenden Tastendruck. Jedenfalls sauschnell.
Hi!

Ich hab mal den findfirst/findnext/findclose Ansatz übernommen und auf reines Zählen reduziert.
Für das Verzeichnis lazarus mit allen Unterverzeichnissen ergibt das:

14849 Datein in 353 Millisekunden

Das wäre dann 1/3 Sekunde nach dem Tastendruck.
Jetzt brauchen wir von charlytango noch eine genaue Definition von "sauschnell".

Source folgt. Windows User müssen die const "StartDirectory" anpassen.

Code: Alles auswählen

var DirAttr : integer;

function Tree (StartDir : String) : integer;
var search : TSearchRec;
begin
{$IFDEF LINUX} DirAttr := 48;
{$ELSE} DirAttr := faDirectory;
{$ENDIF}
result := 0;
if startDir[length(startDir)] <> DirectorySeparator then
   startDir := startDir + DirectorySeparator;

if findFirst(startDir+'*',faAnyFile,search) = 0 then
    begin
    repeat
      if (search.name = '.') or (search.name = '..') then Continue;
      if (search.Attr = DirAttr) then result := result + Tree(startDir+search.Name) else
           inc (result);
    until FindNext(search) <> 0;
    end;
findClose(search);
end;

procedure TForm1.Button9Click(Sender: TObject);
const startDirectory = '/usr/lib64/lazarus/';
var filenum : Integer;
    StartTime, EndTime : QWord;
begin
   StartTime := GetTickCount64;
   fileNum := tree(startDirectory);
   EndTime := GetTickCount64;
   showMessage (IntToStr(fileNum)+' Dateien in '+LineEnding +
                IntToStr (EndTime-StartTime)+' ms' );
end;
           


Grüße
Winni

Benutzeravatar
theo
Beiträge: 10468
Registriert: Mo 11. Sep 2006, 19:01

Re: Dateien zählen

Beitrag von theo »

@Winni: Kommt halt auch aufs Medium und evtl. aufs Dateisystem an.
Ich habe z.B. rund 200GB Musik auf einer externen HD (FAT32).
Da dauert das auslesen der ID3 Tags schon etwas länger (30 Minuten).
Ich bin mir aber nicht sicher, wie das mit dem reinen Zählen ist.
Bekommt man das nicht relativ direkt z.B. aus der "File Allocation Table"?
Kennt sich da jemand aus?

charlytango
Beiträge: 843
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: Dateien zählen

Beitrag von charlytango »

Winni hat geschrieben:
Fr 12. Mär 2021, 12:57

14849 Datein in 353 Millisekunden

Das wäre dann 1/3 Sekunde nach dem Tastendruck.
Jetzt brauchen wir von charlytango noch eine genaue Definition von "sauschnell".
Oh, habe ich da irgendwie einen Ehrgeiz gekitzelt ;)

Aber DANKE gleich fürs Testen denn das wollte ich entspannt am Wochenende machen.
Die 1/3 Sekunde kann wohl schon als sauschnell klassifiziert werden.

ich mag das Klima hier im Forum -- und auch die fachliche Expertise
nochmals herzlichsten Dank - case closed

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: [Erledigt] Dateien zählen

Beitrag von six1 »

jetzt könnte man nochmal mit FindAllFiles vergleichen...
https://wiki.freepascal.org/FindAllFiles
Gruß, Michael

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Dateien zählen

Beitrag von Socke »

theo hat geschrieben:
Fr 12. Mär 2021, 13:35
@Winni: Kommt halt auch aufs Medium und evtl. aufs Dateisystem an.
Ich habe z.B. rund 200GB Musik auf einer externen HD (FAT32).
Da dauert das auslesen der ID3 Tags schon etwas länger (30 Minuten).
Ich bin mir aber nicht sicher, wie das mit dem reinen Zählen ist.
Bekommt man das nicht relativ direkt z.B. aus der "File Allocation Table"?
Kennt sich da jemand aus?
Ich hatte mal gelesen, dass die Dateisuche schneller geht, wenn man erst ein komplettes Verzeichnis durch iteriert und erst danach in die Unterverzeichnisse absteigt.
Das hängt mit Sicherheit an den Zugriffsmustern des Mediums und Datenstrukturen des Dateiystems zusammen.

Bei einer HDD hast du typischerweise einen Read-Ahead, der weitere Daten nach den angeforderten Daten bereits im Dateisystemcache des Betriebssystems lädt. Ist an dieser Position das selbe Verzeichnis abgelegt, kannst du dieses schneller auslesen als ein Unterverzeichnis, das an ganz anderer Stelle auf der Scheibe gespeichert ist.
Bei SSDs spielt das technisch bedingt nur eine untegordnete Rolle.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: [Erledigt] Dateien zählen

Beitrag von Winni »

Hi!

ID Tags: Dazu müssen die Dateien jeweils angefasst werden. Bei ID3v1 geht das noch recht einfach: es sind die letzten 128 Bytes der Datei. Bei den modernerneren Tags ist es komplexer.

Look ahead und Buffer: Selbst Windows puffert inzwischen look ahead Daten. Linux macht das schon ewig, allen ungenutzten RAM für die Buffers zu reservieren. Den Effekt kann man z.B. derart vorführen:
Man macht ein "find" über das gesamte Dateisystem. Das dauert. Dabei zieht er sich aber alle Verzeichnisse in die Buffers. Wenn man jetzt wieder ein find eingiebt - auch mit einem anderen Suchbegriff - geht das "sauschnell".

Natürlich kommt es auf das Dateisystem an: fat16,fat32, extfat sind ziemlich dumm und langsam.
ext2/3/4 sind schneller; NTFS auch.

Soviel ich weiss, hält kein Dateisystem die Anzahl der benutzten Dateien pro Verzeichnis vorrätig: kann man ja zählen.

Und natürlich kommt es auf die Hardware an. Mach das mal mit ner Festplatte von 1990 - falls Du noch irgenwo nen IDE Port hast. Da kannst Du Kaffee kochen gehen!

Und so betrachtet sind SDDs ein echter Fortschritt. Bis zu dem Tag, an dem man dort Daten retten muss. Da ist es dann oft eiin Totalschaden.

Winni

Antworten