[PB 4.00] Leere Ordner erkennen

Anfängerfragen zum Programmieren mit PureBasic.
CNESM
Beiträge: 311
Registriert: 29.08.2004 15:16
Kontaktdaten:

[PB 4.00] Leere Ordner erkennen

Beitrag von CNESM »

Hallo,

da mein Chef nun irgendwie herausbekommen hat, das ich ein bissle programmieren kann, wurde ich nun indirekt dazu bestimmt, den Arbeitsalltag meines Chefs und unserer Abteilung durch kleine Tools zu revolutionieren ;) .... und das als Industriekaufmann und jahrelanger Pause im Programmieren :/

Bei den letzten drei kleinere Tools lief alles ohne Probleme. Leider hänge ich beim letzten ein wenig im Seil. Versuche schon seit Stunden da durchzublicken, aber sämtliche Tests laufen bei mir nun in noch tiefere Unwissenheit.

Kleines Erklärung: Wir haben duzende Netzwerklaufwerke, die vor Jahren mal angelegt wurden und neben vielen nützliche Sachen auch viel Müll in Form von unzähligen GB beinhalten. Nun soll ich ein Tool schreiben, das folgendes macht:

- Bestimmte Dateien/Ordner in einem anderen Verzeichnis abspeichern
- Ältere Dateien durch neue ersetzen
- Leere Ordner erkennen und verschieben (Damit meinen wir Ordner die KEINEN Inhalt haben. Als Inhalt zählt bei uns aber noch Nullbyte-Dateien, leere Ordner und versteckte Dateien. Also nur Ordner die wirklichen KEINEN Inhalt haben, sind bei auch wirklich "leer")

Und genau beim letzten Problem hänge ich nun. Die Prozedur zum Durchsuchen der Verzeichnisse habe ich mal einfach strukturiert unten aufgezeigt. Wie also muss man die Proc ergänzen, das mir beispielsweise in einer Messagebox angezeigt wird "Der Ordner XXX ist völlig leer"?

Anmerkung: Ich hab natülrich die Suchfunktion benutzt, doch leider habe ich keine Möglichkeit gefunden, die an meine vorgegebene Procedur passt. Da ich gerade davon spreche: Die unten aufgezeigte Procedur sollte so wenig wie möglich verändert werden!

Ich wäre euch sehr dankbar, wenn ich euch das mal anschauen könntet. Witme mich derweil den nächsten Tool, muss ja mal weiterkommen - irgendwie :(

Code: Alles auswählen

Procedure PfadDurchsuchen(dir$,start,Art)

If ExamineDirectory(start,dir$,"*.*")
   Repeat 
   Type=NextDirectoryEntry()

   
   If Type=2 ;Path

      If DirectoryEntryName()<>"." And DirectoryEntryName()<>".."
         c$=dir$+DirectoryEntryName()+"\"
         PfadDurchsuchen(c$,start+1,Art)
         UseDirectory(start)
      EndIf

   ElseIf Type=1 ;File


   EndIf

   Until Type=0
EndIf
EndProcedure
P.S. Ja ich weiß muss updaten *AufPurebasicVersionImHeaderKuck*
Zuletzt geändert von CNESM am 24.01.2007 21:21, insgesamt 1-mal geändert.
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag von edel »

Wenn du PB aktualisiert hast kannst du mal folgeden Code testen.

Beispiel : (nur Windows)

Code: Alles auswählen

Procedure PfadDurchsuchen(dir$)
  
  dir = ExamineDirectory(#PB_Any,dir$,"*.*")
  
  
  PathAddBackslash_(dir$) ; WinAPI32 - ab IE 4
  ;oder 
  ; if not Right(dir$,1) = "\"
     ; dir$ + "\"
  ; EndIf
  
  If dir
    
    while NextDirectoryEntry(dir)
      
      name.s = DirectoryEntryName(dir)  
      
      if DirectoryEntryType(dir) =  #PB_DirectoryEntry_Directory
        if not name = "." and not name = ".."  
          PfadDurchsuchen(dir$+name)
        else
          Continue
        EndIf 
      EndIf
      
      if PathIsDirectoryEmpty_(dir$ + name) ; WinAPI32 - ab IE 5
        debug dir$ + name 
      EndIf
      
    Wend 
    FinishDirectory(dir)
  EndIf
  
endProcedure

pfadDurchsuchen("d:\")
CNESM
Beiträge: 311
Registriert: 29.08.2004 15:16
Kontaktdaten:

Beitrag von CNESM »

Hallo,

erstmal danke für den Code und für einen möglichen Lösungsansatz!! Werd den Code gleich morgen auf der Arbeit mal testen! Was mich etwas stutzig macht, ist die Angabe "WinAPI32 - ab IE 5". Bin schon den ganzen Tag am grübeln, das es doch eigentlich eine deutlich weniger "Microsoft abhängige" Variante geben müsste? Ich frage das, weil wir in der Firma keinen IE nutzen. Das Nachinstallierend der benötigten DLL sollten durch unser Benutzereinschränkungen auch nicht möglich sein. Aufgrund dessen wäre deine Variante für mich nicht nutzbar, auch wenn Sie ihren Zweck wohl zu 100% erfüllen wird!
Benutzeravatar
bobobo
jaAdmin
Beiträge: 3873
Registriert: 13.09.2004 17:48
Kontaktdaten:

Beitrag von bobobo »


PathAddBackslash


Adds a backslash to the end of a string to create the correct syntax for a path. If the source path already has a trailing backslash, no backslash will be added.
so ne alberne mickrige Stringfunktion kann man sehr wohl durch was
Selbstgehäkeltes ersetzen.

Dasselbe gilt für PathIsDirectoryEmpty, was nur ermittelt, ob ein
Verzeichnis leer ist.


Wer für sowas die API anwirft ist ein fauler Sack und hat kein Linux :)
‮pb aktuel 6.2 windoof aktuell und sowas von 10
Ich hab Tinnitus im Auge. Ich seh nur Pfeifen.
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Es gibt aber ein Problem, wenn du leere Ordner entfernen willst.
Angenommen, im Laufwerk C: befindet sich "myOrdner", darin nur ein Ordner "temp" und in "temp" ist noch ein Ordner "leer". Sonst sind keine weiteren Dateien in "C:\myOrdner" zu finden.

Beim ersten Suchlauf wirst du feststellen:
"C:\myOrdner\" ist nicht leer,
"C:\myOrdner\temp" ist nicht leer, ABER
"C:\myOrdner\temp\leer\" ist leer.

Also löschst du Ordner "leer", übrig bleibt also folgender Pfad: "C:\myOrdner\temp\"

Beim nächsten Scan wirst du feststellen:
"C:\myOrdner\" ist nicht leer,
""C:\myOrdner\temp\" ist leer.


Sobald also ein Ordner nur einen Ordner und sonst nichts enthält und irgendwann ein Ordner kommt, der seinerseits nichts enthält, verhält sich dein Probgramm genauso wie in diesem Beispiel: Pro Suchdurchlauf wird also der unterste/letzte Ordner gelöscht, weil der ja leer ist. Die Ordner darüber sind nicht leer, denn die enthalten ja den leeren Ordner. Im Beispiel würdest du also nach mehreren Scans nacheinander die Ordner "leer", dann "temp", dann "myOrdner" löschen. Ursprünglich, also beim 1. Scan, wolltest du "myOrdner" aber doch nicht löschen, weil beim 1. Scan war der ja noch nicht leer.
Mit dem Beispiel wollte ich dich auf dieses logische Problem aufmerksam machen.

Somit musst du deine Aussage:
Leere Ordner erkennen und verschieben (Damit meinen wir Ordner die KEINEN Inhalt haben. Als Inhalt zählt bei uns aber noch Nullbyte-Dateien, leere Ordner und versteckte Dateien. Also nur Ordner die wirklichen KEINEN Inhalt haben, sind bei auch wirklich "leer")
also noch mal kräftig überdenken!
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

edel hat geschrieben:

Code: Alles auswählen

...
  PathAddBackslash_(dir$) ; WinAPI32 - ab IE 4
  ;oder 
  ; if not Right(dir$,1) = ""
     ; dir$ + ""
  ; EndIf
den auskommentierten codeteil habt ihr wohl geflissentlich übersehen?

erst lesen, dann meckern!
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
vonTurnundTaxis
Beiträge: 2130
Registriert: 06.10.2004 20:38
Wohnort: Bayreuth
Kontaktdaten:

Beitrag von vonTurnundTaxis »

Schlimm, schlimm... Davon abgesehen: Warum verwendet ihr nicht einfach "/" statt "\"
C:/ geht genau so wie C:\ - und so ist schon mal eine Hürde fürs eventuelle Portieren genommen.
Nicht durch Zorn, sondern durch Lachen tötet man
ClipGrab | Pastor - jetzt mit kurzen URLs!
CNESM
Beiträge: 311
Registriert: 29.08.2004 15:16
Kontaktdaten:

Beitrag von CNESM »

Über die Backslash Dinge machen ich mir derweil ehrlich gesagt KEINE Sorgen :mrgreen:

Was mit jetzt noch ein Problem aufwirft, ist das von AND51 aufgezeigte Verhalten der Procedur (Danke schonmal dafür!!). Hatte ich im ganzen Hin und Her nicht beachtet!

Ich kann leider meine Wunschvorstellung nicht anpassen. Die Situatuon ist so wie sie ist und dafür muss ich jetzt irgendwie ne Lösung finden:

Ich müsste also Quasie "von hinten" anfangen und die Ganze Geschichte aufarbeiten d.h.

"C:\myOrdner\temp\leer\" ist leer und enthält KEINE Dateien/Ordner (Anzahl und Größe=0)

Ergebnis= Ordner wird gelöscht

usw.

Ist sowas überhaupt möglich?!
Benutzeravatar
vonTurnundTaxis
Beiträge: 2130
Registriert: 06.10.2004 20:38
Wohnort: Bayreuth
Kontaktdaten:

Beitrag von vonTurnundTaxis »

So?

Code: Alles auswählen

Procedure DeleteEmptyFolders(Folder.s)
    Protected ID
    Protected Not_Empty
    ID = ExamineDirectory(#PB_Any, Folder, "*")
    
    While NextDirectoryEntry(ID)
        Select DirectoryEntryType(ID)
            Case #PB_DirectoryEntry_Directory
                If DirectoryEntryName(ID) <> "." And DirectoryEntryName(ID) <> ".."
                    Not_Empty + DeleteEmptyFolders(Folder + "/" + DirectoryEntryName(ID))
                EndIf
            Case #PB_DirectoryEntry_File
                Not_Empty = 1
        EndSelect
    Wend
    FinishDirectory(ID)
    If Not_Empty = 0
        DeleteDirectory(Folder, "*")
    EndIf
    ProcedureReturn Not_Empty
EndProcedure


DeleteEmptyFolders("/Blöder/böser/Pfad")
Nicht durch Zorn, sondern durch Lachen tötet man
ClipGrab | Pastor - jetzt mit kurzen URLs!
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Ich hab auch mal was gebastelt. Der Code funktioniert aber nur ab PB V4.00:

Code: Alles auswählen

Structure IsDirectoryEmpty
  id.l      ;Directory-ID nach Öffnen des Verzeichnisses
  Files.l   ;Anzahl der Dateien im Verzeichnis
  rFiles.l  ;Anzahl der Dateien in den Unterverzeichnissen
  *pDir.IsDirectoryEmpty
  Path.s    ;Pfad des Verzeichnisses
EndStructure
Procedure IsDirectoryEmpty(Dir.s, Empty.s(), Recursiv = #True) ;Return: Anzahl Dateien in Dir.s
  Protected NewList Dir.IsDirectoryEmpty(), Path.s = "", *pDir, Files.l
  
  If Right(Dir, 1) <> "\" : Dir + "\" : EndIf
  
  ClearList(Empty())
  If AddElement(Dir()) = 0 : ProcedureReturn #False : EndIf
  
  Dir()\Path = Dir
  Dir()\id = ExamineDirectory(#PB_Any, Dir, "")
  
  Repeat
    If NextDirectoryEntry(Dir()\id)
      Select DirectoryEntryType(Dir()\id)
        Case #PB_DirectoryEntry_Directory
          Path = DirectoryEntryName(Dir()\id)
          If Path <> "." And Path <> ".."
            Path = Dir()\Path + Path + "\"
            *pDir = @Dir()
            If AddElement(Dir())
              Dir()\pDir = *pDir
              Dir()\Path = Path
              Dir()\id = ExamineDirectory(#PB_Any, Path, "")
              If Dir()\id = 0
                DeleteElement(Dir())
                *pDir = 0
              EndIf
            Else
              *pDir = 0
            EndIf
          EndIf
        
        Case #PB_DirectoryEntry_File
          Dir()\Files + 1
      EndSelect
    
    Else ;wenn das Verzeichnis fertig ist
      If Dir()\pDir ;Wenn es ein Vorgängerverzeichnis gibt
        Dir()\pDir\rFiles + Dir()\Files + Dir()\rFiles
      EndIf
      
      If Dir()\Files = 0 And (Dir()\rFiles = 0 Or Recursiv = #False) ;Wenn es keine Dateien in diesem und/oder alle Untervezeichnissen gibt
        If AddElement(Empty())
          Empty() = Dir()\Path + " (" + Str(Dir()\rFiles) + ")"
        EndIf
      EndIf
      
      Files = Dir()\Files + Dir()\rFiles
      FinishDirectory(Dir()\id)
      DeleteElement(Dir())
    EndIf
  Until CountList(Dir()) = 0
  
  ProcedureReturn Files
EndProcedure

NewList Leer.s()

Debug ""
Debug "Leere Verzeichnisse mit leeren Unterverzeichnissen:"
Debug IsDirectoryEmpty("C:\Programme\", Leer(), #True)
ForEach Leer()
  Debug Leer()
Next


Debug ""
Debug "Verzeichnisse ohne Dateien: (in Klammern Dateien in Unterverzeichnissen)"
Debug IsDirectoryEmpty("C:\Programme\", Leer(), #False)
ForEach Leer()
  Debug Leer()
Next
Antworten