Page 2 of 2

Re: Directory recursion

Posted: Tue Feb 21, 2023 11:09 pm
by mk-soft
Who needs it as a thread ...
See Mini Thread Control Example 4

Mentioned only in passing

Re: Directory recursion

Posted: Tue Feb 21, 2023 11:51 pm
by jacdelad

Code: Select all

Structure DirStruct
  Directory.s
  List FileList.s()
  SubDirCount.l
EndStructure

Global Dir.DirStruct

Procedure.i RecurseThruDirectories(*directoryStruct.DirStruct)
  Protected NewList TempList.s(),exa,temp$,dir$
  AddElement(TempList())
  TempList()=*directoryStruct\Directory
  If Right(TempList(), 1) <> #PS$
    TempList() = TempList() + #PS$
  EndIf
  *directoryStruct\SubDirCount=0
  ClearList(*directoryStruct\FileList())
  While ListSize(TempList())
    FirstElement(TempList())
    dir$=TempList()
    exa=ExamineDirectory(#PB_Any,dir$,"*.*")
    If exa
      While NextDirectoryEntry(exa)
        temp$=DirectoryEntryName(exa)
        If DirectoryEntryType(exa)=#PB_DirectoryEntry_Directory
          If ReplaceString(temp$,".","")<>""
            *directoryStruct\SubDirCount+1
            AddElement(TempList())
            TempList()=dir$+temp$+#PS$
          EndIf
        Else
          AddElement(*directoryStruct\FileList())
          *directoryStruct\FileList()=dir$+temp$
          Debug dir$+temp$
        EndIf
      Wend
    EndIf
    FirstElement(TempList())
    DeleteElement(TempList())
  Wend
EndProcedure

OpenConsole()
Print("Directory: ")
dir$=Input()
If dir$<>""
  Dir\Directory=dir$
  RecurseThruDirectories(Dir)
  PrintN("Subdirectories: "+Str(Dir\SubDirCount))
  PrintN("Files: "+Str(ListSize(Dir\FileList())))
  PrintN("FileList:")
  ForEach Dir\FileList()
    PrintN(Dir\FileList())
  Next
EndIf
PrintN("Done")
If I didn't make a mistake or failed to understand something about threads, this version should work for threaded and unthreaded usage (aka you can call it as an own thread too).

Re: Directory recursion

Posted: Wed Feb 22, 2023 1:36 am
by RichAlgeni
jacdelad wrote: Tue Feb 21, 2023 9:41 pmBut again, and without trying to be counterproductive, I think this way (including the global variables) is not a good way to do the task.
Then let's see if we can teach you something, shall we? Simple integer addition is atomic. That means the addition is guaranteed to succeed, regardless if the process is threaded or not. What isn't guaranteed, is to know the value of the integer, immediately prior to the addition. This is where we would use atomic functions. Had I intended to present threads, I would have done so. What I did I present, was recursion.

Re: Directory recursion

Posted: Wed Feb 22, 2023 3:32 am
by idle
I think a depth first traversal of a Directory listing is a good example for teaching recursion or introducing the idea.

you could have used this as a base or reference, perhaps the names not the best for searching
viewtopic.php?p=394408#p394408

You need to add a check if the directory number is valid or it will crash line 44

Code: Select all

directoryNumber = ExamineDirectory(#PB_Any, directoryName, "*.*")  
    If directoryNumber  
       while NextDirectoryEntry(directoryNumber) 
       ;...
       wend 
    Endif 
Did you consider other recursive algorithms like Fibonacci Numbers or Towers of Hanoi (that used to always blow the 1st years minds) If someone doesn't know how recursion works, they're not really going to be able to use it to good effect. Some things are easy to solve with recursion and others not so much.

Code: Select all

Procedure.q Fibonacci_Rec(n.i)
  If (n < 2) 
    ProcedureReturn n 
  Else 
    ProcedureReturn Fibonacci_Rec(n - 1) + Fibonacci_Rec(n - 2)
  EndIf   
EndProcedure    
    
Procedure.q Fibonacci_Iter(n.i)
  Protected vnow.q = 0
  Protected vnext.q = 1 
  Protected vtemp.q 
  
  While n-1 > 0 
      n-1
      vtemp = vnow + vnext
      vnow = vnext       
      vnext = vtemp       
    Wend 
  ProcedureReturn vnext;	
  
EndProcedure    
	
For a = 0 To 20 
	Debug Str(a) + " = " + Str(Fibonacci_Rec(a)) 
	Debug Str(a) + " = " + Str(Fibonacci_Iter(a)) 
Next 


btw I don't think Add mnemonic is atomic, you can make it atomic by adding the Lock prefix or using C intrinsic functions

Re: Directory recursion

Posted: Wed Feb 22, 2023 8:52 am
by AZJIO
jacdelad
I doubt it will be fast.

Code: Select all

ReplaceString(temp$,".","")<>""
you will be forced to look for a dot in each file name and replace it with a void, while allocating memory for a new line.

My version was like this, although it also requires a double comparison, but fortunately this comparison will break off at the 1st character

Code: Select all

If name = "." Or name = ".."
	Continue
EndIf
Now I propose a new option, since I learned to check the text by listing the letters. This should run faster as it is done in one pass.

Code: Select all

Define name.s = "..."
*c.Character = @name
If *c\c = '.'
	*c + SizeOf(Character)
	If *c\c = '.'
		*c + SizeOf(Character)
		If *c\c = 0
			Debug ".."
			End
; 			Continue
		EndIf
	ElseIf *c\c = 0
		Debug "."
		End
; 		Continue
	EndIf
EndIf
Debug "yes: " + name
test

Code: Select all

EnableExplicit
DisableDebugger
Define i, StartTime
Define name.s = "."
Define name.s = "dfgdsfgdsfgdsf.dfg"
Define Res.s, Res1.s, Res2.s
Define *c.Character

StartTime = ElapsedMilliseconds()

For i = 1 To 1000000
	*c.Character = @name
	If *c\c = '.'
		*c + SizeOf(Character)
		If *c\c = '.'
			*c + SizeOf(Character)
			If *c\c = 0
				Continue
			EndIf
		ElseIf *c\c = 0
			Continue
		EndIf
	EndIf
Next

Res.s = Str(ElapsedMilliseconds() - StartTime) + " ms"

StartTime = ElapsedMilliseconds()
For i = 1 To 1000000
	If name = "." Or name = ".."
		Continue
	EndIf
Next

Res1.s = Str(ElapsedMilliseconds() - StartTime) + " ms"

StartTime = ElapsedMilliseconds()
For i = 1 To 1000000
	If ReplaceString(name,".","")=""
		Continue
	EndIf
Next

Res2.s = Str(ElapsedMilliseconds() - StartTime) + " ms"

EnableDebugger

Debug Res
Debug Res1
Debug Res2

Re: Directory recursion

Posted: Wed Feb 22, 2023 6:34 pm
by mk-soft
Nonsense,

there's no need to look for any points here.

Directory entry "." is the reference to the current directory and must be ignored.
Directory entry "..." is the reference to the parent directory and must be ignored.

These directory entries are no longer supplied, depending on the system.

Everything else that contains one or more dots are valid directory or file names. The last dot in the file name is the separation to the sufix (file type identifier).

Re: Directory recursion

Posted: Wed Feb 22, 2023 6:50 pm
by AZJIO
mk-soft
What will the first two elements be?
Do we need them in the list we want to get?

Code: Select all

i = 0
id = ExamineDirectory(#PB_Any, "C:\Windows\", "")
If id
	While NextDirectoryEntry(id)
		Debug DirectoryEntryName(id)
		i+1
		If i = 3
			End
		EndIf
	Wend
	FinishDirectory(id)
EndIf

Re: Directory recursion

Posted: Wed Feb 22, 2023 10:21 pm
by mk-soft
These are not used to create lists of directories or files.


They are still needed for relative path specifications. With "../pathname" the parent path is referenced from where the path starts. And on Unix/Linux-based systems, programmes are started in the terminal with "./prg-name" in the current path.

Re: Directory recursion

Posted: Thu Feb 23, 2023 2:24 pm
by Axolotl
mk-soft wrote: Wed Feb 22, 2023 6:34 pm ...
Directory entry "..." is the reference to the parent directory and must be ignored.
...
@mk-soft,
you are right, there is only a little typo -> parent directory is represented by two points ".."