Alle Dateien finden: Problem der Endlosschleife

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Oli
Beiträge: 11
Registriert: Di 27. Sep 2022, 13:35

Alle Dateien finden: Problem der Endlosschleife

Beitrag von Oli »

Ich versuche ausgehend von einem Startordner alle Dateien inkl. der Dateien in den Unterordnern zu finden. Dazu habe ich FindAllFiles benutzt. Das Problem ist, dass FindAllFiles auch symbolischen Links folgt, die letztlich zu einer unendlichen Schleife führen können (zum Beispiel dann, wenn in einem Unterordner ein symbolischer Link auf einen Elternordner zu finden ist). Soweit ich recherchiert habe, kann FreePascal/Lazarus plattformunabhängig nicht zwischen Ordnern und symbolischen Links auf Ordner unterscheiden. Auch ChatGPT konnte mir keine Lösung vorschlagen. Gibt es tatsächlich keine Möglichkeit, plattformunabhängig alle Dateien zu finden, ohne eventuell in eine Endlosschleife zu geraten?

ArchChem
Beiträge: 105
Registriert: Mo 11. Jul 2022, 10:41

Re: Alle Dateien finden: Problem der Endlosschleife

Beitrag von ArchChem »

Hallo,

du müsstest sehr wahrscheinlich eine entsprechende Find-Funktion selbst implementieren und dabei manuell überprüfen, ob es sich bei den gefundenen Elementen um einen symbolischen Link handelt.

Auf StackOverflow wurden verschiedene Ansätze, Symlinks in Pascal ausfindig zumachen, zusammengetragen. Ich habe keinen davon getestet, aber vielleicht hilft es dir ja: https://stackoverflow.com/questions/137 ... freepascal

Mathias
Beiträge: 6956
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Alle Dateien finden: Problem der Endlosschleife

Beitrag von Mathias »

du müsstest sehr wahrscheinlich eine entsprechende Find-Funktion selbst implementieren und dabei manuell überprüfen, ob es sich bei den gefundenen Elementen um einen symbolischen Link handelt.
Evtl. mit FindFirst und FindNext

https://www.freepascal.org/docs-html/rt ... first.html
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Oli
Beiträge: 11
Registriert: Di 27. Sep 2022, 13:35

Re: Alle Dateien finden: Problem der Endlosschleife

Beitrag von Oli »

Vielen Dank für die Tipps, die aber (meiner Meinung nach) das Problem leider nicht lösen. Ich werde deshalb jetzt ein Shell-Script (für Linux) bzw. eine Batch-Datei (für Windows) erstellen, die die gefundenen Dateien in eine Textdatei schreiben. Mit TProcess führe ich das Sript aus und lese dann die Textdatei ein. Das ist sicherlich nicht elegant, hilft mir aber vermutlich weiter.

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 385
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Alle Dateien finden: Problem der Endlosschleife

Beitrag von Jorg3000 »

Hi!
Ich hatte das Problem zwar noch nicht, aber nun habe ich mal folgende Zeile in meine Funktion mit einer FindFirst/FindNext-Schleife eingebaut.

Code: Alles auswählen

if (not AcceptSymLinks) and (SearchRec.Attr and faSymLink = faSymLink) then Continue;
Ich hoffe, dass das Problem damit erledigt sein sollte, oder?
Grüße, Jörg

ArchChem
Beiträge: 105
Registriert: Mo 11. Jul 2022, 10:41

Re: Alle Dateien finden: Problem der Endlosschleife

Beitrag von ArchChem »

Oli hat geschrieben: So 28. Jul 2024, 16:40 Vielen Dank für die Tipps, die aber (meiner Meinung nach) das Problem leider nicht lösen.
Warum denkst du, dass das dein Problem nicht löst?

Ich würde eine rekursive Funktion schreiben, die einen Ordner und die Suchmaske als Parameter übergeben bekommt und ein Array mit den absoluten Dateipfaden der Treffer zurückgibt.
Findet die Funktion einen Unterordner, wird überprüft, ob der Unterordner ein symbolischer Link ist (wie das geht, findest du auf Stackoverflow), und falls ja, ruft die Funktion sich mit dem Unterordner selbst auf und fügt die Ergebnisse dem Array hinzu.

Hier ein rudimentärer Aufbau der Funktion (halb Pascal, halb Pseudocode :D )

Code: Alles auswählen

function FindInFilesWithoutSymlink(entrypath: String; pattern: String): Array of String
begin
  {Die Logik für das Finden hier implementieren}

  For file in GefundeneErgebnisse do
  begin
    if (file is NormalFile) and FileNameMatchesWithPattern then 
    {Ergebnisse dem Array hinzufügen}
    begin 
      SetLength(Result, Length(Result)+1)
      Result[Length(Result)-1] = GefundenerDateiPfad
    end

  else if file is FolderNotSymlink then
    Result := Result + FindInFilesWithoutSymlink(GefundenerOrdner, pattern);  
end;
Hier könnte man natürlich noch eine Beschränkung für eventuelle Endlosschleifen einbauen, indem man der Funktion einen Integer übergibt und bei jedem Funktionsaufruf hochzählt und ab einer bestimmten Rekursionstiefe abbricht. Aber der Ansatz sollte eigentlich funktionieren.

Oli
Beiträge: 11
Registriert: Di 27. Sep 2022, 13:35

Re: Alle Dateien finden: Problem der Endlosschleife

Beitrag von Oli »

Vielen Dankfür die weiteren Hinweise. Auch mit FindFirst und FindNext lässt sich meiner Meinung nach das Problem nicht lösen, solange faSymLink nicht portabel ist. Ich habe (unter Linux) folgendes versucht: Zuerst erstelle ich mittels eines Shell-Skript drei Ordnet mit Dateien und symbolischen Links:

Code: Alles auswählen

#!/bin/bash
mkdir ~/tmp1
mkdir ~/tmp2
mkdir ~/tmp1/tmp11

touch ~/tmp1/a.txt
touch ~/tmp1/b.txt
touch ~/tmp1/tmp11/c.txt
touch ~/tmp2/d.txt

cd
ln -s ~/tmp2/ ~/tmp1/Link_zu_tmp2
ln -s ~/tmp1/ ~/tmp2/Link_zu_tmp1
Die symbolischen Links verweisen von tmp1 auf tmp2 und umgekehrt. Wenn ich das nachstehende Programm ausführe, kommt es zu einer Endlosschleife.

Code: Alles auswählen

program project1;

uses
  Classes,
  SysUtils,
  Strutils;

procedure Suchen(Ordner:String);
// Sucht rekursiv alle Dateien,
// beginnend mit Ordner
var
  Info : TSearchRec;
  Ordner2 : String;
  OrdnerNeu : String;
begin
  Ordner2 := Ordner + PathDelim + '*';
  If FindFirst (Ordner2,faAnyFile,Info)=0 then
    begin
    Repeat
      With Info do
      begin
        If (Attr and faDirectory) = faDirectory then
        begin
          if (Name <> '.') and (Name <> '..') then
          begin
            Writeln('Ordner:'+ Ordner + PathDelim + Name);
            Suchen(Ordner + PathDelim + Name);
          end;
        end
        else
          Writeln('Datei:'+ Name);
      end;
    Until FindNext(info)<>0;
    FindClose(Info);
    end;
end;

begin
  Suchen('/home/oliver/tmp1');
  Writeln ('Finished');
end.
Eine Prüfung mit faSymLink auf symbolische Links ist leider nicht portable (Versionen Lazarus 2.2.0, FPC 3.2.2), also nicht unabhängg vom Betriebssystem. Als Hilfslösung führe ich in meinem Pascal-Programm das folgende Shell-Skript (Linux) aus, das alle Dateien in eine Textdatei schreibt (für Windows mache ich prinzipiell das gleiche mit einer Batch-Datei).

Code: Alles auswählen

#!/bin/bash
#find.sh Startordner Ausgabedatei
exec 2>/dev/null
/usr/bin/find $1 -type f >> $2

Mathias
Beiträge: 6956
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Alle Dateien finden: Problem der Endlosschleife

Beitrag von Mathias »

Soweit ich recherchiert habe, kann FreePascal/Lazarus plattformunabhängig nicht zwischen Ordnern und symbolischen Links auf Ordner unterscheiden.
Was eine Möglichkeit wäre, mit FindFirst/FindNext einzulesen und vor zu prüfen, ob es ein Link ist, wen ja, dan keine Rekursivität.

Versuche mal dies hier.
Hat mit ChatGPT in einer C-Version gegeben, welche ich umgeschrieben habe.
Der Testlauf funktionierte.

Code: Alles auswählen

program Project1;

uses
  SysUtils,
  unix,
  BaseUnix;

  procedure Test(path: PChar);
  var
    filestat: Stat;
  begin
    if fpLstat(path, @filestat) = -1 then begin
      WriteLn('lstat');
    end;
    if fpS_ISREG(filestat.st_mode) then begin
      WriteLn('normale Datei');
    end else if fpS_ISDIR(filestat.st_mode) then begin
      WriteLn('Ordner');
    end else if fpS_ISLNK(filestat.st_mode) then begin
      WriteLn('S-Link');
    end else begin
      WriteLn('Anderer Typ');
    end;
  end;

begin
  Test('/home/tux/Schreibtisch/filestest/main.c');   // nornal
  Test('/home/tux/Schreibtisch/filestest/test');     // Ordner
  Test('/home/tux/Schreibtisch/filestest/test.c');   // Link
end.  
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

djdhg
Beiträge: 18
Registriert: Mo 8. Apr 2013, 17:12
OS, Lazarus, FPC: Win11, Debian 12.5, Lazarus: 2.2.6, FPC: 3.2.2
CPU-Target: 64Bit

Re: Alle Dateien finden: Problem der Endlosschleife

Beitrag von djdhg »

Aus https://build.alb42.de/fpcbin/docu/html ... first.html
faSymlink - Report symlinks instead of following them
[...]
Since faSymlink is not included in faAnyFile, to find all possible files and symlinks you need to call FindFirst so:

Code: Alles auswählen

if FindFirst('*', faAnyFile or faSymLink, info)=0 then
Lg

Oli
Beiträge: 11
Registriert: Di 27. Sep 2022, 13:35

Re: Alle Dateien finden: Problem der Endlosschleife

Beitrag von Oli »

Nochmals Danke für Eure Antworten. Mathias' Lösung funktioniert unter Linux einwandfrei, das werde ich mir gerne merken. Da ich allerdings auch unter Windows eine Lösung brauche, behelfe ich mir wie oben beschrieben mit Shell- und Batch-Skripten. Ich denke, mit den Lösungsvorschlägen können wir meine Frage als ausreichend beantwortet sehen. Vielen Dank.

Mathias
Beiträge: 6956
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Alle Dateien finden: Problem der Endlosschleife

Beitrag von Mathias »

Oli hat geschrieben: Di 30. Jul 2024, 22:36 Nochmals Danke für Eure Antworten. Mathias' Lösung funktioniert unter Linux einwandfrei, das werde ich mir gerne merken. Da ich allerdings auch unter Windows eine Lösung brauche, behelfe ich mir wie oben beschrieben mit Shell- und Batch-Skripten. Ich denke, mit den Lösungsvorschlägen können wir meine Frage als ausreichend beantwortet sehen. Vielen Dank.
Da ich allerdings auch unter Windows eine Lösung brauche.
Mach es doch auf diese Art:

Code: Alles auswählen

  {$IFDEF Linux}
  sdl3_lib = 'SDL3';
  {$ENDIF}
  {$IFDEF Windows}
  sdl3_lib = 'SDL3.dll';
  {$ENDIF}
Schau mal in die Datei "osmacro.inc", da gibt es noch mehr zu auswerten.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
Zvoni
Beiträge: 396
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: Alle Dateien finden: Problem der Endlosschleife

Beitrag von Zvoni »

Workaround-Versuch: Sammel erst alle Ergebnisse die ausschliesslich Ordner sind --> https://lazarus-ccr.sourceforge.io/docs ... ories.html
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Antworten