Jump to content

[Solved] FileFindNextFile only returns 1 files, despite * search.


Recommended Posts

This script is suppose to check all files in a given folder (@scriptdir) and it's sub folders for a certain pattern (common duplicate filenames) and if found, add them to an array to be removed via FileRecycle(). The problem is in _Search() function. It only checks a single file in any given folder. Does anyone have any ideas on what is happening here? The syntax looks right to me, but clearly I am missing something here.

I added some ConsoleWrite debug lines to assist with debugging the code and the FileRecycle line has been commented out, so no files will actually get recycled. I also included a test folder for you. Just change FileChangeDir(@ScriptDir) at the top to where you extracted the folder or place the script in the same folder as the test folder.

;#RequireAdmin
#include <Array.au3>
#include <File.au3>
#include <FileConstants.au3>
#include <MsgBoxConstants.au3>

;Change to script directory. This fixes searching in the wrong folder when used from a shortcut with an improperly set Working Directory.
FileChangeDir(@ScriptDir)

;Enables a Progress Bar
ProgressOn("Recycling Duplicates", "Getting list of folders")

;Get a list of folders to search
$aFolders = _FileListToArrayRec(@WorkingDir, "*", $FLTA_FOLDERS, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH)

;Create variable for list of duplicate files.
Global $aList[0]

;Start a timer to update the Progress Bar.
Global $timer = TimerInit()

;Assign a variable to track the number of found duplicates.
Global $iCount = 0

;Searches the @ScriptDir ROOT folder for duplicates to recycle.
_Search(@WorkingDir)

;Searches every folder recursively in the @ScriptDir ROOT folder for duplicates to recycle.
For $i = 1 To $aFolders[0]

    ;If timer is greater than specified value on the right, update the Progress Bar with the current information.
    If TimerDiff($timer) > (1000 / 29) Then

        ;Update the Progress Bar
        ProgressSet(($i * 100) / ($aFolders[0]), "Searching " & $i & " of " & $aFolders[0] & " for duplicates." & @CRLF & "Found " & $iCount & " duplicates.", "Searching for Duplicates...")

        ;Start a new timer to update the Progress Bar.
        $timer = TimerInit()
    EndIf

    ;Change Working Directory to the folder being searched.
    FileChangeDir($aFolders[$i])

    ;Search folder for duplicates to recycle.
    _Search($aFolders[$i])
Next

;This allows the progress bar to fully complete itself graphically.
ProgressSet(100, "Searching " & $i & " of " & $aFolders[0] & " for duplicates." & @CRLF & "Found " & $iCount & " duplicates.", "Searching for Duplicates...")
Sleep(500)

If $iCount = 0 Then
    ;Disables Progress Bar
    ProgressOff()

    ;Inform user that no duplicates were detected.
    MsgBox($MB_APPLMODAL, "Recycling Duplicates", "No duplicates were found. The program will now exit.")
    Exit
EndIf


;Get the number of duplicates so we can properly update the progress bar.
_ArrayInsert($aList, 0, UBound($aList), 0)

;Restart the timer
$timer = TimerInit()

;For each duplicate, recycle the file.
For $j = 1 To $aList[0]

    ;If timer is greater than specified value on the right, update the Progress Bar with the current information.
    If TimerDiff($timer) > (1000 / 29) Then
        ;Update the Progress Bar
        ProgressSet(($j * 100) / ($aList[0]), "Recycling duplicate " & $j & " of " & $aList[0] & ".", "Recycling Duplicates...")

        ;Start a new timer to update the Progress Bar.
        $timer = TimerInit()
    EndIf

    ;Recycle the file

    ;TESTING ONLY - NO FILES ARE ACTUALLY BEING RECYCLED.
    ;$iRecycle = FileRecycle($aList[$j])
    ;If $iRecycle = False Then MsgBox($MB_SYSTEMMODAL, "Recycling Duplicates", "An error occurred whilst recycling the file.")
Next

;This allows the progress bar to fully complete itself graphically.
ProgressSet(100, "Recycling duplicate " & $j & " of " & $aList[0] & ".", "Recycling Duplicates...")
Sleep(500)

;Disables Progress Bar
ProgressOff()

;Inform user that all detected duplicates have been moved to the Recycling Bin. This implies that duplicates can be restored from the recycling bin or permanently deleted.
MsgBox($MB_APPLMODAL, "Recycling Duplicates", "All found duplicates have been moved to the Recycling Bin.")

; Open the recycle bin by using the following CLSID.
ShellExecute("::{645FF040-5081-101B-9F08-00AA002F954E}")
Func _Search($Dir)

    ; Assign a Local variable the search handle of all files in the current directory.
    Local $hSearch = FileFindFirstFile("*")

    ; Check if the search was successful. If not, returns False and search the next folder.
    If $hSearch = -1 Then Return False

    ; Assign a Local variable the empty string which will contain the files names found.
    Local $sFileName = "", $iResult = 0

    Local $vCount=0

    While 1
        $sFileName = FileFindNextFile($hSearch)
        ; If there is no more file matching the search, exit the loop and search the next folder.
        If @error Then ExitLoop
        $vCount+=1
        ConsoleWrite("Checking "&$Dir&"\"&$sFileName&" >> ")

        Select ;Blacklist certain duplicates
            Case StringInStr($sFileName, "(1)")
            Case StringInStr($sFileName, "(2)")
            Case StringInStr($sFileName, "(3)")
            Case StringInStr($sFileName, "(4)")
            Case StringInStr($sFileName, "(5)")
            Case StringInStr($sFileName, "(6)")
            Case StringInStr($sFileName, "(7)")
            Case StringInStr($sFileName, "(8)")
            Case StringInStr($sFileName, "(9)")
            Case StringInStr($sFileName, "(conflicted)")
            Case StringInStr($sFileName, "(conflicted 1)")
            Case StringInStr($sFileName, "(conflicted 2)")
            Case StringInStr($sFileName, "(conflicted 3)")
            Case StringInStr($sFileName, "(conflicted 4)")
            Case StringInStr($sFileName, "(conflicted 5)")
            Case StringInStr($sFileName, "(conflicted 6)")
            Case StringInStr($sFileName, "(conflicted 7)")
            Case StringInStr($sFileName, "(conflicted 8)")
            Case StringInStr($sFileName, "(conflicted 9)")
            Case StringInStr($sFileName, "-BetaLaptop")
            Case Else ;Everything else is ignored.
                ConsoleWrite("[Ignored]"&@CRLF)
                ExitLoop
        EndSelect

        ;Add to recycle list.
        ConsoleWrite("[Marked]"&@CRLF)
        $iret = _ArrayAdd($aList,@WorkingDir & "\" & $sFileName)
        If $iret = -1 Then MsgBox($MB_SYSTEMMODAL, "Recycling Duplicates", "An error occurred whilst adding the file to the list of duplicates." & @CRLF & "Error: " & @error)

        ;Increment counter
        $iCount += 1

    WEnd
    ConsoleWrite("Checked " & $vCount & " items."&@CRLF)
    ; Close the search handle.
    FileClose($hSearch)
EndFunc   ;==>_Search


 

Recycle Copies.au3

Test Folder.7z

EDIT: Solved. I still don't know why it didn't work, but I realized I could use a different method to do what I was wanting. Fixed script is at https://www.autoitscript.com/forum/topic/195000-filefindnextfile-only-returns-1-files-despite-search/?do=findComment&comment=1398443

Edited by BetaLeaf
Solved

 

 

Link to comment
Share on other sites

Shouldn't it be

Local $hSearch = FileFindFirstFile("*.*")

to search for all files?

Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

AFAIK, *.* matches any filename and any extension. I'm also trying to search for files that have no extension. I also just realized since I just need to get a list of files, I can just use _FilesListToArray instead. 

So yea, I solved it on my own. I had originally needed a search, but later realised the search was missing some other types of duplicates I was searching for. Better to just list all files and check if it matches a substring. Here's the fixed script.

Recycle Copies.au3

 

 

Link to comment
Share on other sites

1) you are correct that _FileListToArrayRec() is indeed sufficient for your purposes.

2) "*" is a more comprehensive form, that should be preferred over "*.*", as it also returns files without extensions.

3) your original issue was the ExitLoop command in the Case Else section.

Edited by orbs

Signature - my forum contributions:

Spoiler

UDF:

LFN - support for long file names (over 260 characters)

InputImpose - impose valid characters in an input control

TimeConvert - convert UTC to/from local time and/or reformat the string representation

AMF - accept multiple files from Windows Explorer context menu

DateDuration -  literal description of the difference between given dates

Apps:

Touch - set the "modified" timestamp of a file to current time

Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes

SPDiff - Single-Pane Text Diff

 

Link to comment
Share on other sites

13 minutes ago, orbs said:

2) "*" is a more comprehensive form, that should be preferred over "*.*", as it also returns files without extensions.

*.* also returns files with no extension, at least in _FileListToArray and the Windows command console.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...