Seite 1 von 3

[PB 4.00] Leere Ordner erkennen

Verfasst: 20.01.2007 14:10
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*

Verfasst: 20.01.2007 15:12
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:\")

Verfasst: 21.01.2007 16:55
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!

Verfasst: 22.01.2007 14:35
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 :)

Verfasst: 22.01.2007 14:44
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!

Verfasst: 22.01.2007 15:24
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!

Verfasst: 22.01.2007 16:05
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.

Verfasst: 22.01.2007 16:40
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?!

Verfasst: 22.01.2007 16:52
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")

Verfasst: 22.01.2007 17:31
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