Archive: Search the hard drive


Search the hard drive
Ok, well here is as far as I have managed to go today.

Push ""
Push C:\
Call SearchDir

I'm not sure what I can do next, just try and get further.


Function SearchDir
Exch $0 ;dir
Exch
Exch $1 ;file
Push $2
Push $3
Push $4
Push $5
Push $6
Push $R0 ;temp file
Push $R1 ;ini no's
Push $R2 ;ini no's
ClearErrors

StrCpy $R1 0
StrCpy $R2 0

# Open temp file
GetTempFileName $R0

# Remove \ from end (if any)
StrCpy $2 $0 1 -1
StrCmp $2 \ 0 +2
StrCpy $0 $0 -1

# Get first file or directory name
ClearErrors
FindFirst $2 $3 "$0\*"
IfErrors end1

# Check if file name = directory name
IfFileExists "$0\$3\*" 0 loop1
WriteINIStr $R0 "Directory Tree" "Value 1" "$0\$3"
IntOp $R1 $R1 + 1

loop1:
# Keep looking for file or directory name
ClearErrors
FindNext $2 $3
IfErrors end1

# Check if file name = directory name
IfFileExists "$0\$3\*" 0 loop1
IntOp $R1 $R1 + 1
WriteINIStr $R0 "Directory Tree" "Value $R1" "$0\$3"
Goto loop1
end1:

StrCpy $R1 0

loop_main:
StrCpy $R2 0

IntOp $R1 $R1 + 1
ReadINIStr $4 $R0 "Directory Tree" "Value $R1"
StrCmp $4 "" done

# Get first file or directory name
ClearErrors
FindFirst $2 $3 "$4\*"
IfErrors end1

# Check if file name = directory name
IfFileExists "$3\*" 0 loop1
WriteINIStr $R0 "Directory Tree" "Value $R1 1" "$4\$3"
IntOp $R2 $R2 + 1

loop2:
# Keep looking for file or directory name
ClearErrors
FindNext $2 $3
IfErrors loop_main

# Check if file name = directory name
IfFileExists "$4\$3\*" 0 loop2
IntOp $R2 $R2 + 1
WriteINIStr $R0 "Directory Tree" "Value $R1 $R2" "$4\$3"
Goto loop2

done:
# Delete temp file
;Delete $R0
ExecShell open $R0
Pop $R2
Pop $R1
Pop $R0
Pop $6
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Exch $0
FunctionEnd


It doesn't even output anything yet.
The first push will be for the file to search for and the output will be the path to the found file or error if no file was found.

I have a lot more to do, and this is very hard to do!

-Stu :o

I've tried your function, and is very interesting.

I put a MessageBox MB_OK '"Value $R1 $R2" "$4\$3"' after the WriteINIStr $R0 "Directory Tree" "Value $R1 $R2" "$4\$3".

But this only search in a folder, and subfolder (i.e. C:\Windows\Menu Iniciar), it don't go in the subfolders of subfolder (like C:\Windows\Menu Iniciar\Programas) and do not search for the file or folder yet.

So the next things to do are:

1)The first thing to do now is to put a code to detect the file before of the code to detect the subfolders (using FindFirst). And if it is in that folder, goto done, and return the value to user.

2)The second thing is, if the file is not detected, put the error flag, and return no value to user (clear with StrCpy $var ""), to do this you will have to change the IfErrors end1, to IfErrors error, and put 'SetErrors' and 'StrCpy $var ""' after the label Error without these single quotes.

3)Third, the most difficult, is the detection of the subfolders of folder, of folder, of folder, of folder, of folder, of folder, of folder, of folder, of folder, of folder. (i.e. C:\Windows\Menu Iniciar\Programas\Acessórios\Jogos\Meu Jogo\Sites do Meu Jogo\Suporte\Nome da Empresa\Link 1.lnk).

And to do this, you have to make loop, on loop9, on loop8, on loop7, on loop6, on loop5, on loop4, on loop3, on loop2, on loop1. So this function will be very big. I don't know if exist a better way than using this (I tried to do this on "Advanced File Size Function, Folder Size Example" using the subfolders, but because the example was too big, I didn't put it at Archive).


I thought that there was no limmit to the ammount of subdirectories?

If there is a limit, then I could finish this function now.

-Stu


Yes, have a limit. Now the limit of your funtion is 3, (C:\Program Files\NSIS).

Add support to more one subdirectory, is to copy the loop, and paste in the location that will work on this loop, the drawbacks of this is that the function will be big, very big, and can use different variables, so it is not too good.

[EDITED]Have another way to do this, but is complicated to understand, and is much difficult to do, but economize space and is unlimited!

In example, C:/Program Files/NSIS, the function detected that the Program Files is the first (1), repeat the code using now the result of this first search (and the code to search in this subfolder), now have three folders, Common Files (1 1), NSIS (1 2) and Winamp (1 3). The first to be searched is Common Files, so it will use the result of the FindNext to repeat the code (and to use the code to search in this subfolder), now using the C:/Program Files/Common Files, the function found nothing here, so will return to the previous result to repeat the code, the next is NSIS, and are what I'm looking so will end the repeatable code and return the result to user.

I will study on this. On the next Saturday I will post the complete function for you here. Or if not, I will say the reason. OK?[/EDITED]


I know what I need to do next, but if you want to do it, I don't mind!
I shall have another go at it, and see how it goes.

-Stu :)


Nearly there
I've nearly cracked this now. I've attached a script which scans a given path for files (wildcards allowed), e.g. find notepad.* in d:/winnt/ or whatever.

It's almost finished. The results of the search are stored in a string ($6) and have the form :-

>dirpath|file|file|file|>dirpath|file

Where the files are matches found in the dirpath specified, e.g.

>d:/winnt/|notepad.exe|>d:/winnt/system32/|notepad.exe

You just then need to walk the string, splitting on the "|" character. Any time a file starts with > you know it's really a directory name and not a file.

I don't have time to finish this right now. I will do later if no-one else beats me to it.

The attached script prints out the results as it goes for debug purposes. You could of course insert your action code where the debug prints out and not worry about the contents of $6... that's up to you.


Comments:

- Your version, Sunjammer is good, it found 1 file in the C:\Windows that have Notepad* and more 3 in Help subfolder and 1 in Applog subfolder of Windows folder, you are really in the right way!

- But have a drawback, it's 5x slow than searching with the Windows Search.

- It don't use much memory, useful for slower computes (I don't know if this is a quality, because that exist much computer that have much RAM), and give the exact results that is given on the Windows Search!

Is really very good, I'm watching to be finished to use in my programs!

But I will make a alternative version of Search Files based on the AfrowUK work, that is a good start, only some changes to make it perfect!

[EDIT]I tested now using MakeNSIS*, and again, give the same results than the Windows Search!

Download and post the comments![/EDIT]


Sunjammer has been beat by a better function!
Made with the base of the Sunjammer and AfrowUK functions, now I will show the power of my function Search File (or Folder). See the qualities of this function (test yet, not finished, I will try to finish today):

- Now suport folder search, Search for the WINAMP folder or NSIS folder!
- Is 1.7 X more quickly than the Windows Searcher!
- Use the maximum memory of your computer for the search!
- This code economize the $6 and $R0 variables.
- Some Fixes.

Try now, and comment what you think (but is a debug test, I'm now tring to complete it, and I'm in the right way)!

[EDIT]This file, show how to detect Winamp folder. It will detect the Start Menu Folder of the Winamp, and the Winamp itself. You can use the function Advanced Search in String to get the value before the "|" and after, and use the command "IfFileExists" to detect if one of these strings is located the Winamp.exe for each string. So you will can find the real Winamp path![/EDIT]


I have also cracked it!
I think it looks like my script is working ok!
However, it takes a very long time to find a file in say 5 subdirectories!

It uses an ini file to write and then read the dir values.
You can find the ini file as %TEMP%\files.lst

Script attached.

I'm trying it out now.

-Stu


Wow, that script works incredibly fast!
I think it works similar to mine, but I see that it does not write to a log.
I'm trying to figure out how it works!

GJ, and put it on the archive!

-Stu :)


You can do it without recursion too, relaying only on the stack which will allow a far more extensive use of memory and will be faster because there are less operations.

The attached script found in less than 3 seconds the file requested and finished running on 10GB of files, 28,000 files, in less than 10 seconds.

Adapted from Justin's script:
http://forums.winamp.com/showthread....ight=findfirst

BTW, if you want to make it run really fast you can write a plug-in to do the job. This will skip all of the NSIS processing.


deguix, FindFirst $2 $3 "C:\something\*." doesn't find all sub directories. It won't find a directry named test.test for example. You should use:

IfFileExists "C:\something\*.*" isDir notDir

to test if a given path points to a directory.


"BTW, if you want to make it run really fast you can write a plug-in to do the job. This will skip all of the NSIS processing."

First, I don't want to be really fast, only that searches with a clean code, and I don't use any compilers, only the NSIS one.

"FindFirst $2 $3 "C:\something\*." doesn't find all sub directories."

Second, I will fix this at Wednesday at night.


Is anyone going to make an archive page out of this or should I?


I'll take that as a no...

http://nsis.sourceforge.net/archive/...php?pageid=266


Macro-izing the search
When trying to write an update tool, I needed something like the examples you all wrote, except that I wanted to have a function called with the directory or file that was found.

For instance, my update tool works over a Novell network share (a mapped drive on our network) and scans the deploy dir (like your find functions). The difference was that when I found a file, I compared it to a file in the installation directory and overwrote if the mod-time was newer, also if it was a dll or ocx register it if the dll version is newer. For directories, did the same.

The find code should really be macro-ized so that you can run code on the searched files/dirs while searching - this makes the code more generic and more useful. Please don't shoot me for saying that!

UPDATE: SORRY, just read the archive and you have done this... well done.


[edit]Heh, never mind :)[/edit]

The version I have put on that Archive page has a callback function that is called for every file found. The callback function can also stop the search. The function should work on a network share too because it gets a directory to search in as a parameter.


I have modified the script (only a couple lines of code) so that it is more general. The implications of this are potentially slower searches for people using this for finding a single file, with the benefit of having the ability to do whatever the user wants for every file in the search when necessary.

I have included the modified version of Kichik's script on the archive page, that now searches for multiple versions of a file (and could do much more).

This makes the scripts resemble POSIX scandir().


Here is my version of Search File, these are the qualities:

- You can search by any folder or file in the hard drive, cdroms...
- You can include subfolders in the search or not.
- Have a option to show the results by Message Boxes and/or Detail Prints too, for each found file or folder.
- By result, the function return the files found string, and the number of files found.
- And a other to refine the result str (hehe)!
- 1.7 x more quickly (than the normal Windows Search) if you don't use the folders with dot, 5.0 x more slowly if you use with dots (it's a drawback, this occur because the files have extension, so will search for every file, and detect if this is a file or directory).
- This is a FUNCTION, without using your valuable variables (uses but return the original ones back)!

Future Plans:

- Put a option to stop to first file found (for those that want only to search one file).
- Make a macro for all the function, to easily the work to copy the function, and to call it.
- Make the Advanced Search For File, to search files with the size, modification date, or searching files for a text (will be more slow, and big, because search for every file information, with several functions in one).

[EDIT]I will fix tomorrow the comments, I don't put any comments how to use it, and I don't have time now[/EDIT]

Here is my version of Search File Function:


Thanks banaman8d, I have added a link in the archive page.


OK! Some fixes and comments now about the pushes! (good code to detect folders with dot is your, Kichik, it have the same velocity of my without dot!)


Search the hard drive For Delete
plz hellp

i con Search the hard drive For Delete

for Example

Search For .txt

find >

>>> Delete or partition Drive Delete

:rolleyes:

POSSIBLE mack for me


http://nsis.sourceforge.net/RecFind:...t%2C_FindClose

Stu


THANKS Afrow UK

IMPOSSIBILITY


${GetDrives} "[Option]" "Function"
"[Option]" ; [FDD+HDD+CDROM+NET+RAM]
; FDD Floppy Disk Drives
; HDD Hard Disk Drives
; CDROM CD-ROM Drives
; NET Network Drives
; RAM RAM Disk Drives
;
; [ALL]
; Find all drives by letter (default)
;
"Function" ; Callback function when found

Function "Function"
; $9 "drive letter" (a:\ c:\ ...)
; $8 "drive type" (FDD HDD ...)

; $R0-$R9 are not used (save data in them).
; ...

Push $var ; If $var="StopGetDrives" Then exit from function
FunctionEnd

for Example

${locate::Open} "j:\" "/F=1 /D=1 /S=,Kb /T=,Creation delete/M=*.nsi /SD=NAME /B=1" $R0

Search For only .nsi file for delete

THANKS