Archive: FindFirst


FindFirst
  Hi

I recommend a small change in the FindFirst usage:

user_var(handle output) user_var(filename output) filespec

or

FindFirst $0 $1 $INSTDIR\*.txt

The documentation claims if no files are found, both outputs ($0 + $1) are set to empty and an error flag is set.

This is only 99% true. If the folder is empty and the file search has 2 wildcards:

FindFirst $0 $1 $INSTDIR\*.*

the first variable returns the search handle (some number), the second variable returns an empty string and no error flag is set.

To check if any files are in the folder, you need:

CmpStr $1 ""

IfErrors is unreliable.

I hope I'm not being petty.


IfErrors is 100% reliable, using wildcards "*.*" returns the dots "." and ".." specifying the directory.


Oops. I didn't see the dot. The second variable returns a decimal point, dot.

I'm beginning to wonder if having two wildcard characters is such a good idea in the search string.

CmpStr $1 "." doesn't feel right.

May I give this over to the experts panel (no offense) to pore over?

Does FindFirst recognize $INSTDIR\*.* to mean any files or subfolders in $INSTDIR?

edit:
Red Wine, you beat me to it.

IfErrors is still inaccurate, since no error flag is set with an empty folder.


Ok, 2 examples to help you a bit :)

outfile 'find.exe'
ShowInstDetails show

section -
SetOutPath "$EXEDIR"
CreateDirectory "$EXEDIR\boo"

FileOpen $R0 "$EXEDIR\boo\test1.txt" w
FileClose $R0
FileOpen $R0 "$EXEDIR\boo\test2.txt" w
FileClose $R0

ClearErrors
FindFirst $0 $1 "$EXEDIR\boo\*.*"
StrCmp $1 "." +2
StrCpy $2 "$1$\r$\n"

loop:
FindNext $0 $1
IfErrors end
StrCmp $1 ".." loop
StrCpy $2 "$2$1$\r$\n"
goto loop

end:
StrCmp $2 "" 0 +2
MessageBox MB_OK "Error! No Files found" IDOK +2
MessageBox MB_OK "Files found: $\r$\n$2"
FindClose $0
Delete "$EXEDIR\boo\test1.txt"
Delete "$EXEDIR\boo\test2.txt"
Rmdir "$EXEDIR\boo"
sectionend


outfile 'find.exe'
ShowInstDetails show

section -
SetOutPath "$EXEDIR"
CreateDirectory "$EXEDIR\boo"

ClearErrors
FindFirst $0 $1 "$EXEDIR\boo\*.*"
StrCmp $1 "." +2
StrCpy $2 "$1$\r$\n"

loop:
FindNext $0 $1
IfErrors end
StrCmp $1 ".." loop
StrCpy $2 "$2$1$\r$\n"
goto loop

end:
StrCmp $2 "" 0 +2
MessageBox MB_OK "Error! No Files found" IDOK +2
MessageBox MB_OK "Files found: $\r$\n$2"
FindClose $0
Rmdir "$EXEDIR\boo"
sectionend

I withdraw my usage proposal.

To find out if the folder is empty, FindNext should loop.

FindFirst $0 $1 $INSTDIR\*.* returns an error if the directory does not exist.

Thx!:)

I used the code below. (Took me a while to figure out though.)


FindFirst $0 $1 "$INSTDIR\*.*"
IfErrors skip
loop:
FindNext $0 $1
IfErrors skip
StrCmp $1 ".." loop
MessageBox MB_ICONSTOP|MB_OK "The folder is not empty."
FindClose $0
Abort

skip:

If you want to check a directory, you may use DirState or Locate .


i worked with RecFind successfully last weeks
http://nsis.sourceforge.net/RecFind:...t%2C_FindClose

it is the more convenient way.


RecFind does a recursive search through the whole directory tree, which is slightly more than I need at the moment. I don't know how to stop it from looping when the folder is not empty. It could explain that better in the examples, imo.

${DirState} "$INSTDIR" $R0
StrCmp $R0 "1" 0 skip

is simpler.

Thanks again.

edit:
A recursive file search tool is impressive.


>> A recursive file search tool is impressive.

Thats a bit tricky...
RecFind seems oversized but it is easy to handle...
it returns "" (emtpy) when he finds another subfolder
just skip to recfindnext

example

;find filemask

>${RecFindOpen} "$FOLDER" $0 $1
StrCmp$0 "" 0 findfile1_done1

>${RecFindFirst}

;your code

>;fetch next file
findfile1_next:
${RecFindNext}

;end file loop
findfile1_done1:
${RecFindClose}
i currently work with an array to grab all folders then fetch files.