#NoTrayIcon #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=C:\Program Files\AutoIt3\Aut2Exe\Icons\AutoIt_Main_v10_256x256_RGB-A.ico #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** If Not @Compiled Then TraySetState() Opt('MustDeclareVars', 1) #include #include #include #include #include #include #include #include #include <_FileListToArrayRecursive.au3> Global $sParentFolder, $aSubfolders, $aCheckParents, $aWinSize[2] = [ 600, 500 ], $aFileListing, $sFilename, $sLogFile = @TempDir & '\FolderDumpErrorLog.txt' Global $iGM, $hGUIMain, $bt_Refresh, $lv_FileList, $ra_ConflictAsk, $ra_ConflictRename, $ra_ConflictSkip, $bt_OKMove, $bt_Exclude If $CmdLine[0] = 1 Then If _IsFolder($CmdLine[1]) Then $sParentFolder = _IsFolder($CmdLine[1], 1) ; Ensure tailing '\' Else Exit MsgBox(0x30, 'Folder Dumper', 'Invalid folder selected:' & @LF & $CmdLine[1]) EndIf ElseIf $CmdLine[0] > 1 Then Dim $aSubfolders[$CmdLine[0]+1] = [ $CmdLine[0] ] $aCheckParents = $aSubfolders For $i = 1 To $CmdLine[0] If Not _IsFolder($CmdLine[$i]) Then Exit MsgBox(0x30, 'Folder Dumper', 'Invalid folder selected:' & @LF & $CmdLine[$i]) Else $aSubfolders[$i] = _IsFolder($CmdLine[$i], 1) $aCheckParents[$i] = StringLeft($aSubfolders[$i], StringInStr($aSubfolders[$i], '\', 0, -2)) EndIf Next $aCheckParents = _ArrayUnique($aCheckParents, 0, 1, 1) If $aCheckParents[0] > 1 Then Exit MsgBox(0x30, 'Folder Dumper', 'Multiple folders with different parents selected.') $sParentFolder = $aCheckParents[1] Else Exit MsgBox(0x30, 'Folder Dumper', 'No folders selected.') EndIf Opt('GUIResizeMode', $GUI_DOCKALL) $hGUIMain = GUICreate('Folder Dumper', 400, 270, Default, Default, $WS_OVERLAPPEDWINDOW) GUICtrlCreateLabel('Dump Folder:', 5, 5, 70, 20, $SS_CENTERIMAGE) GUICtrlCreateInput($sParentFolder, 75, 5, 255, 20, BitOR($GUI_SS_DEFAULT_INPUT, $ES_READONLY)) GUICtrlSetResizing(-1, BitOR($GUI_DOCKALL, $GUI_DOCKRIGHT)) $bt_Refresh = GUICtrlCreateButton('Refresh', 330, 5, 65, 20) GUICtrlSetResizing(-1, BitOR($GUI_DOCKSIZE, $GUI_DOCKRIGHT, $GUI_DOCKTOP)) ;~ $lv_FileList = GUICtrlCreateListView('#|Name|Path', 5, 30, 390, 200, $LVS_SHOWSELALWAYS, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_CHECKBOXES)) $lv_FileList = GUICtrlCreateListView('#|Name|Path', 5, 30, 390, 200, $LVS_SHOWSELALWAYS) GUICtrlSetResizing(-1, $GUI_DOCKBORDERS) Opt('GUIResizeMode', BitOR($GUI_DOCKSIZE, $GUI_DOCKLEFT, $GUI_DOCKBOTTOM)) GUICtrlCreateLabel('File name conflicts:', 5, 240, 90, 20, $SS_CENTERIMAGE) $ra_ConflictAsk = GUICtrlCreateRadio('&Ask', 100, 240, 40, 20) GUICtrlSetTip(-1, 'Ask for each conflict') GUICtrlSetState(-1, $GUI_CHECKED) $ra_ConflictRename = GUICtrlCreateRadio('&Rename', 140, 240, 60, 20) GUICtrlSetTip(-1, 'Rename file numerically (ie: Filename.txt => Filename (1).txt)') $ra_ConflictSkip = GUICtrlCreateRadio('&Skip', 200, 240, 55, 20) GUICtrlSetTip(-1, 'Leave file in folder') $bt_OKMove = GUICtrlCreateButton('Move', 295, 235, 100, 30) GUICtrlSetFont(-1, 12) GUICtrlSetResizing(-1, BitOR($GUI_DOCKSIZE, $GUI_DOCKRIGHT, $GUI_DOCKBOTTOM)) GUISetState() ControlFocus($hGUIMain, '', $bt_OKMove) WinMove($hGUIMain, '', (@DesktopWidth - $aWinSize[0])/2, (@DesktopHeight - $aWinSize[1])/2, $aWinSize[0], $aWinSize[1]) _GetFiles() While 1 $iGM = GUIGetMsg() Switch $iGM ;~ Case $bt_Exclude ;~ $iSelCount = _GUICtrlListView_GetSelectedCount($lv_Files) ;~ If $iSelCount > 1 Then ;~ $aSelItems = _GUICtrlListView_GetSelectedIndices($lv_Files, True) ;~ $sCopyString = '' ;~ For $i = 1 To $aSelItems[0] ;~ $sCopyString &= _GUICtrlListView_GetItemText($lv_Files, $aSelItems[$i]) & @CRLF ;~ Next ;~ $sCopyString = StringTrimRight($sCopyString, 2) ;~ Else ;~ $sCopyString = _GUICtrlListView_GetItemText($lv_Files, _GUICtrlListView_GetNextItem($lv_Files)) ;~ EndIf Case $bt_Refresh _GetFiles() Case $bt_OKMove _MoveFiles() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd Func _GetFiles() _GUICtrlListView_BeginUpdate($lv_FileList) Do _GUICtrlListView_DeleteAllItems($lv_FileList) Local $aFileRecurse[1] = [ 0 ], $iGroupItemCount = 0 If IsArray($aSubfolders) Then Local $temp _GUICtrlListView_EnableGroupView($lv_FileList) _GUICtrlListView_InsertGroup($lv_FileList, -1, 1, 'Selected subfolders') For $i = 1 To $aSubfolders[0] $temp = _FileListToArrayRecursive($aSubfolders[$i], '*', BitOR(4, 8, 16)) _ArrayConcatenate($aFileRecurse, $temp) GUICtrlCreateListViewItem($i & ':|' & $aSubfolders[$i], $lv_FileList) _GUICtrlListView_SetItemGroupID($lv_FileList, $iGroupItemCount, 1) $iGroupItemCount += 1 Next $temp = 0 _GUICtrlListView_InsertGroup($lv_FileList, -1, 2, 'Contents') $aFileRecurse[0] = UBound($aFileRecurse)-1 If Not $aFileRecurse[0] Then GUICtrlCreateListViewItem('||No files found', $lv_FileList) _GUICtrlListView_SetColumnWidth($lv_FileList, 2, $LVSCW_AUTOSIZE) _GUICtrlListView_SetItemGroupID($lv_FileList, 1, 1) ExitLoop EndIf Else Local $aFileRecurse = _FileListToArrayRecursive($sParentFolder, '*', BitOR(4, 16));, '_Filter') If @error Then GUICtrlCreateListViewItem('||No files found', $lv_FileList) _GUICtrlListView_SetColumnWidth($lv_FileList, 2, $LVSCW_AUTOSIZE) ExitLoop EndIf EndIf Global $aFileListing[$aFileRecurse[0]+1][3] Local $iCount = 0 For $i = 1 To $aFileRecurse[0] $sFilename = StringTrimLeft($aFileRecurse[$i], StringInStr($aFileRecurse[$i], '\', 0, -1)) If $sFilename = StringTrimLeft($aFileRecurse[$i], StringLen($sParentFolder)) Then ContinueLoop $aFileListing[$i][0] = $sFilename $aFileListing[$i][1] = $aFileRecurse[$i] ; Note: This is filling an array index with names prefixed with a number indicating file (0) or folder (1). ; This allows me to sort by this index later so folders are processed last when moving everything. If _IsFolder($aFileRecurse[$i]) Then $aFileListing[$i][2] = '1 ' & $sFilename Else $aFileListing[$i][2] = '0 ' & $sFilename EndIf $iCount += 1 Next _ArraySort($aFileListing, 1, 1) ; Sort descending to put empties at bottom ReDim $aFileListing[$iCount+1][3] ; Crop out empties _ArraySort($aFileListing, 0, 1, 0, 2) ; Sort by flag/name index $aFileListing[0][0] = $iCount For $i = 1 To $aFileListing[0][0] GUICtrlCreateListViewItem($i & ':|' & $aFileListing[$i][0] & '|' & $aFileListing[$i][1], $lv_FileList) If IsArray($aSubfolders) Then _GUICtrlListView_SetItemGroupID($lv_FileList, $iGroupItemCount, 2) $iGroupItemCount += 1 EndIf Next _GUICtrlListView_SetColumnWidth($lv_FileList, 0, $LVSCW_AUTOSIZE) _GUICtrlListView_SetColumnWidth($lv_FileList, 1, $LVSCW_AUTOSIZE) _GUICtrlListView_SetColumnWidth($lv_FileList, 2, $LVSCW_AUTOSIZE) Until 1 _GUICtrlListView_SetItemChecked($lv_FileList, -1) _GUICtrlListView_EndUpdate($lv_FileList) EndFunc Func _MoveFiles() Local $iConflictDefault, $iConflictResolve If GUICtrlRead($ra_ConflictRename) = $GUI_CHECKED Then $iConflictDefault = 1 ElseIf GUICtrlRead($ra_ConflictSkip) = $GUI_CHECKED Then $iConflictDefault = 2 EndIf GUISetState(@SW_DISABLE) ProgressOn('Folder Dumper', 'Moving files...', '', Default, Default, 2+16) Local $hProg = WinGetHandle('Folder Dumper', 'Moving files...') Local $iErrorCount For $i = 1 To $aFileListing[0][0] ProgressSet(100*($i / $aFileListing[0][0]), $aFileListing[$i][0] & ' <= ' & $aFileListing[$i][1]) If FileExists($sParentFolder & $aFileListing[$i][0]) Then If Not $iConflictDefault Then $iConflictResolve = _Prompt($aFileListing[$i][0], $aFileListing[$i][1]) If @extended Then $iConflictDefault = $iConflictResolve If $iConflictResolve = -1 Then ExitLoop Else $iConflictResolve = $iConflictDefault EndIf Switch $iConflictResolve Case 1 $aFileListing[$i][0] = _WinAPI_PathStripPath(_WinAPI_PathYetAnotherMakeUniqueName($sParentFolder & '\' & $aFileListing[$i][0])) Case 2 ContinueLoop EndSwitch EndIf If StringLeft($aFileListing[$i][2], 1) = 1 Then If Not DirMove($aFileListing[$i][1], $sParentFolder & $aFileListing[$i][0]) Then $iErrorCount += 1 _Log($aFileListing[$i][1], $sParentFolder & $aFileListing[$i][0]) EndIf Else If Not FileMove($aFileListing[$i][1], $sParentFolder & $aFileListing[$i][0]) Then $iErrorCount += 1 _Log($aFileListing[$i][1], $sParentFolder & $aFileListing[$i][0]) EndIf EndIf Next ProgressOff() _GetFiles() GUISetState(@SW_ENABLE) WinActivate($hGUIMain) If $iErrorCount > 0 And MsgBox(0x2134, 'Folder Dumper', $iErrorCount & ' error(s) moving files. Check the error log for more details.' & @LF & 'Would you like to view the log file now?', 0, $hGUIMain) = 6 Then ShellExecute($sLogFile) EndIf EndFunc Func _FileMove($a, $b) ConsoleWrite('> ' & $a & @CRLF & '+ ' & $b & @CRLF) Return 1 EndFunc Func _DirMove($a, $b) Return _FileMove($a, $b) EndFunc Func _Prompt($sFilename, $sFilepath) Local $hGUIPrompt, $aGMPrompt, $bt_PromptRename, $bt_PromptSkip, $bt_PromptCancel, $ch_PromptRepeat $hGUIPrompt = GUICreate('Filename Conflict', 300, 170, Default, Default, BitOR($WS_CAPTION, $WS_POPUP, $WS_SYSMENU), Default, $hGUIMain);, $hProg) GUICtrlCreateLabel('Cannot move file:', 5, 5, 290, 15) GUICtrlCreateInput($sFilepath, 5, 20, 290, 20, BitOR($GUI_SS_DEFAULT_INPUT, $ES_READONLY)) GUICtrlCreateLabel('Filename already exists:', 5, 40, 290, 15) GUICtrlCreateInput($sFilename, 5, 55, 290, 20, BitOR($GUI_SS_DEFAULT_INPUT, $ES_READONLY)) GUICtrlCreateLabel('How do you want to proceed?', 5, 85, 290, 15, $SS_CENTER) $bt_PromptRename = GUICtrlCreateButton('Rename', 120-65, 110, 60, 25) GUICtrlSetTip(-1, 'Rename file numerically (ie: Filename.txt => Filename (1).txt)') $bt_PromptSkip = GUICtrlCreateButton('Skip', 120, 110, 60, 25) GUICtrlSetTip(-1, 'Leave file in folder') $bt_PromptCancel = GUICtrlCreateButton('Cancel', 120+65, 110, 60, 25) GUICtrlSetTip(-1, 'Cancel moving files') $ch_PromptRepeat = GUICtrlCreateCheckbox('Repeat for all', 110, 140, 80, 20) GUISetState() ControlFocus($hGUIPrompt, '', $bt_PromptCancel) Local $iReturn = 0, $iExtended = 0 Do Local $aGMPrompt = GUIGetMsg(1) If $aGMPrompt[1] = $hGUIPrompt Then Switch $aGMPrompt[0] Case $bt_PromptRename $iReturn = 1 Case $bt_PromptSkip $iReturn = 2 Case $bt_PromptCancel, $GUI_EVENT_CLOSE $iReturn = -1 EndSwitch EndIf Until $iReturn If GUICtrlRead($ch_PromptRepeat) = $GUI_CHECKED Then $iExtended = 1 GUIDelete($hGUIPrompt) Return SetExtended($iExtended, $iReturn) EndFunc Func _IsFolder($sPath, $iSuffix = 0) If $iSuffix Then If StringRight($sPath, 1) <> '\' Then $sPath &= '\' Return $sPath EndIf If StringInStr(FileGetAttrib($sPath), 'D') Then Return 1 EndFunc Func _Log($sFrom, $sTo) _FileWriteLog($sLogFile, StringFormat('Cannot move file:\r\n Source: %s\r\n Destination: %s', $sFrom, $sTo)) EndFunc