ivan Posted June 25, 2005 Posted June 25, 2005 Hi Guys! As embarassed as I can be about putting forward this simple question, I can't figure out how i can combine the FileFindFirstFile and FileFindNextFile statements to build a list of subdirectory paths and files starting at @scriptdir like: C:\Documents and Settings\ivan\img119.html C:\Documents and Settings\ivan\xxxxxxxx\img119.jpg C:\Documents and Settings\ivan\xxxxxxxx\yyyyyyyy\img12.html C:\Documents and Settings\ivan\xxxxxxxx\yyyyyyyy\zzzzzzzzzzzzz\img12.jpg ETC........................ I normally use batch files in ms-DOS with autoit, for example: dir /a-d /b /on /s>FileList.txt The -d parameter excludes subdirectories themselves, leaving just paths and file names, and the command dumps a neat list of files starting where I launch the bat file. Unfortunately for me, this time the directory contains files with Spanish characters such as ñ, é, Á, and the likes, which are dumped with errors in unicode (8.3). If I get a grip with FileFindFirstFile and FileFindNextFile I'll attach a code to this post, but all I managed so far is some really silly code. HELP PLEASE!! If anyone has come across a solution to this problem before, I would really appreciate it if you could share it with me. Thanks in advance. IVAN Think out of the boxGrabber: Yet another WinInfo tool_CSVLib (still alpha)Dynamic html in au3
ezzetabi Posted June 25, 2005 Posted June 25, 2005 (edited) $a = _FileSearch(@scriptdir & '\*') expandcollapse popupFunc _FileSearch($sIstr) ; An array is returned with the full path of all files found. The pos [0] keeps the number of elements. Local $sCriteria, $sBuffer, $iH, $iH2, $sCS, $sCF, $sCF2, $sCP, $sFP, $sOutPut = '', $aNull[1] $sCP = StringLeft($sIstr, StringInStr($sIstr, '\', 0, -1)) If $sCP = '' Then $sCP = @WorkingDir & '\' $sCriteria = StringTrimLeft($sIstr, StringInStr($sIstr, '\', 0, -1)) If $sCriteria = '' Then $sCriteria = '*.*' ;To begin we seek in the starting path. $sCS = FileFindFirstFile($sCP & $sCriteria) If $sCS <> - 1 Then While 1 $sCF = FileFindNextFile($sCS) If @error Then FileClose($sCS) ExitLoop EndIf If $sCF = '.' Or $sCF = '..' Or StringInStr(FileGetAttrib($sCP & $sCF), 'd') Then ContinueLoop $sOutPut = $sOutPut & $sCP & $sCF & @LF WEnd EndIf $sBuffer = @CR & $sCP & '*' & @LF;The buffer is set for keeping the given path plus a *. Do $sCS = StringTrimLeft(StringLeft($sBuffer, StringInStr($sBuffer, @LF, 0, 1) - 1), 1);current search. $sCP = StringLeft($sCS, StringInStr($sCS, '\', 0, -1));Current search path. $iH = FileFindFirstFile($sCS) If $iH <> - 1 Then While 1 $sCF = FileFindNextFile($iH) If @error Then FileClose($iH) ExitLoop EndIf If $sCF = '.' Or $sCF = '..' Then ContinueLoop If StringInStr(FileGetAttrib($sCP & $sCF), 'd') Then $sBuffer = @CR & $sCP & $sCF & '\*' & @LF & $sBuffer; Every folder found is added in the begin of buffer $sFP = $sCP & $sCF & '\'; for future search $iH2 = FileFindFirstFile($sFP & $sCriteria); and checked with the criteria. If $iH2 <> - 1 Then While 1 $sCF2 = FileFindNextFile($iH2) If @error Then FileClose($iH2) ExitLoop EndIf If $sCF2 = '.' Or $sCF2 = '..' Or StringInStr(FileGetAttrib($sFP & $sCF2), 'd') Then ContinueLoop $sOutPut = $sOutPut & $sFP & $sCF2 & @LF;Found items are put in the Output. WEnd EndIf EndIf WEnd EndIf $sBuffer = StringReplace($sBuffer, @CR & $sCS & @LF, '') Until $sBuffer = '' If $sOutPut = '' Then $aNull[0] = 0 Return $aNull Else Return StringSplit(StringTrimRight($sOutPut, 1), @LF) EndIf EndFunc ;==>_FileSearch Edit: _FileSearch altered so its should not return directories. Edit2: Tested, it works with extended ASCII charactes (like èòà), but not with real unicode (like ありがとう ) Edited June 25, 2005 by ezzetabi
ivan Posted June 25, 2005 Author Posted June 25, 2005 Wow!! thanks! That was fast!!!!!! i think i saw this udf in a forum search i did about three hours ago. i'll try this UDF and i'll let you know if i had any problems. cheers ivan Think out of the boxGrabber: Yet another WinInfo tool_CSVLib (still alpha)Dynamic html in au3
ezzetabi Posted June 25, 2005 Posted June 25, 2005 I read your post better, if you just want to write a file list in a file. Change the return part of the UDF from If $sOutPut = '' Then $aNull[0] = 0 Return $aNull Else Return StringSplit(StringTrimRight($sOutPut, 1), @LF) EndIf to Return StringTrimRight($sOutPut, 1) (and remove $aNull from declarations) So the function will return a @lf separed list, ready to be write where you want.
ivan Posted June 25, 2005 Author Posted June 25, 2005 Thanks. I executed the script but the machine crashed as the root i'm using has about 10000 files. I modified the script but it'll take a couple of hours till i see the result... IVAN Think out of the boxGrabber: Yet another WinInfo tool_CSVLib (still alpha)Dynamic html in au3
ezzetabi Posted June 26, 2005 Posted June 26, 2005 My script crashed? Very strange. I tested also in very big folders but after a while it gave the correct result. Anyway, if you improved the script share it with us improvements are always welcomed.
blindwig Posted June 26, 2005 Posted June 26, 2005 I have 2 UDFs that you might want to look at. I designed them to return arrays containing large numbers of files. They even show a progress bar during the search.Here's the link:http://www.autoitscript.com/forum/index.ph...ic=12835&hl=UDF My UDF Threads:Pseudo-Hash: Binary Trees, Flat TablesFiles: Filter by Attribute, Tree List, Recursive Find, Recursive Folders Size, exported to XMLArrays: Nested, Pull Common Elements, Display 2dSystem: Expand Environment Strings, List Drives, List USB DrivesMisc: Multi-Layer Progress Bars, Binary FlagsStrings: Find Char(s) in String, Find String in SetOther UDF Threads I Participated:Base64 Conversions
ivan Posted June 29, 2005 Author Posted June 29, 2005 Does anyone know how to sort the array using the _FileSearch UDF according to the filezise? Everything worked fine with the script shared by ezzetabi. Thanks a lot again, you don't cease to amaze me! This next challenge might help a lot of us who keep backup copies of our files, without ever deleting them.... I've used ezzetabi's UDF to create a script which compares the byte size of each file with the rest of the files down the array and if they are equal, I run the DOS command FC /B file1 file2, which does a binary comparison of the said files. If FC returns a text string on the second line saying that the there is no difference between the files (which i output to a text file), then it's safe to assume the files are identical and one of them can be deleted. Otherwise, if the output text file contains more than two lines, then the the files are different, so instead of waiting for hours, I close the fc.exe process using ProcessClose("fc.exe"). I'm not posting the script here yet as a precaution to other AUTOIT posters. In fact, I split the process in two scripts, the first one is ezzetabi's modified _FileSearch UDF to work with western-european characters, and which outputs the result to a text file. At this point I modify the list manually. Then I run my script made up of a for..next loop embedded in another to run FC. As you can see, it is still a work in progress and if used incorrectly, someone might accidentally delete permanently a large number of files from their drive... The advantage is that, after 4 days, I managed to recover over 7 gb of rubbish on my drive by deleting identical files (keeping a really disorganized file structure though), but it's ok as I kept a map of the drive's tree structure. Basically i want to join the two scripts, and shorten the entire process, for which i'll need to sort the array according to the file size. Any help would be greatly appreciated, as always. Think out of the boxGrabber: Yet another WinInfo tool_CSVLib (still alpha)Dynamic html in au3
blindwig Posted June 29, 2005 Posted June 29, 2005 Does anyone know how to sort the array using the _FileSearch UDF according to the filezise?You probably want to modify it to return a 2-dimensional array, where the filesize is stored in a 2nd column. Then you can use _ArraySort to sort based on that second column. Remember to set the file sizes as number, not string, to get the sort order correct.If FC returns a text string on the second line saying that the there is no difference between the files (which i output to a text file), then it's safe to assume the files are identical and one of them can be deleted. Otherwise, if the output text file contains more than two lines, then the the files are different, so instead of waiting for hours, I close the fc.exe process using ProcessClose("fc.exe").Neat trick. I believe there is a UDF for comparing files inside AutoIt, but I don't know how it's speed compares to FC My UDF Threads:Pseudo-Hash: Binary Trees, Flat TablesFiles: Filter by Attribute, Tree List, Recursive Find, Recursive Folders Size, exported to XMLArrays: Nested, Pull Common Elements, Display 2dSystem: Expand Environment Strings, List Drives, List USB DrivesMisc: Multi-Layer Progress Bars, Binary FlagsStrings: Find Char(s) in String, Find String in SetOther UDF Threads I Participated:Base64 Conversions
ivan Posted June 29, 2005 Author Posted June 29, 2005 Thanks. I had the same thought and i'm in the process of experimenting with a dummy folder and dummy files. I don't think i modified _FileSearch UDF correctly though as i've just seen the first results and the files don't match their respective size after sorting the array. Think out of the boxGrabber: Yet another WinInfo tool_CSVLib (still alpha)Dynamic html in au3
steve8tch Posted June 29, 2005 Posted June 29, 2005 This gives a slightly messy listing. $x = Run(@ComSpec & " /c dir /a-d /b /on /s", "", @SW_HIDE,2) $line = "" While 1 $line =$line & StdoutRead($x) If @error = -1 Then ExitLoop Wend FileWrite(@ScriptDir & "\file_list.txt",$line) You will need the beta to run this.
ivan Posted June 29, 2005 Author Posted June 29, 2005 Thanks Steve. As I mentioned on the opening topic, I first tried using the DOS command: dir /a-d /b /on /s>FileList.txt from a bat file but the directory contains Spanish characters such as ñ, é, Á, and the likes, and dir outputs rubbish on those characters. I get a correct result with the _FileSearch UDF and I am trying to modify it so I can get a two dim array containing file name and size. Think out of the boxGrabber: Yet another WinInfo tool_CSVLib (still alpha)Dynamic html in au3
jamesband Posted June 29, 2005 Posted June 29, 2005 give this a try expandcollapse popup#include <Array.au3> dim $dir[1], $dircount, $hDir, $temp dim $file, $path, $attrib dim $list $dir[0] = "c:\download" $dircount = 1 $x = 0 $hList = fileopen("filelist.txt", 2) while ($x < $dircount) $hDir = filefindfirstfile($dir[$x]&"\*.*") if not ($hDir = -1) then $file = filefindnextfile($hDir) while not @error $path = $dir[$x]&"\"&$file $attrib = filegetattrib($path) select case ($file = ".") ;nothing case ($file = "..") ;nothing case (isDir($path)) ;msgbox(0,"Found Dir:", $file) _arrayadd($dir, $path) $dircount = $dircount + 1 case else ;msgbox(0,"Found File:", $file) filewriteline($hList, $path) endselect $file = filefindnextfile($hDir) wend endif fileclose($hDir) $x = $x + 1 wend fileclose($hList) ;------------------------------------------------------------ func isDir($chkDir) if (stringinstr(filegetattrib($chkDir),"D")) then return 1 else return 0 endif endfunc
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now