Corrupted / 0 byte file finder

Post your working scripts, libraries and tools for AHK v1.1 and older
xcloudx01
Posts: 4
Joined: 05 Oct 2017, 00:27

Corrupted / 0 byte file finder

05 Oct 2017, 00:57

This tool scans your computer for any files which are 0 bytes in size. Often a file that gets corrupted becomes 0 bytes.
I've had random exe, iso and video files become corrupted for no reason, so I made this to find every potentially corrupted file so I can get rid of/replace them.

Instructions:

Select the folder you'd like to scan, and if you'd like to scan sub-directories.
Click the "Find zero byte files" button.
If any 0 byte files are detected, a list will open up detailing them. Double click to go to them in explorer, right click to delete them or copy their path.
Don't just randomly delete every single thing it finds, figure out if what it found is something of importance, like if the file is one of your family videos or something.

GitHub with compiled version for download: https://github.com/Draqen4/Empty-Corrupted-File-Finder/

Code: Select all

;Environment
;Version: 1.023. 8th Oct 2017
#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
#SingleInstance Force
SetBatchLines,-1 ;Thanks Helgef <3

;Variables
NameOfProgram = xcloudx01's Empty File Finder
;Get settings from ini file. Check to see if .ini file exists first.
Ifexist,ZeroByteFinderSettings.ini
{
			fileread,Temp,ZeroByteFinderSettings.ini
			ifinstring,Temp,[settings]
				GoSub,LoadSettings
			Else
				gosub, SetDefaultVariableValues
}
Else
	gosub, SetDefaultVariableValues

;GUI
Gui, Add, Text, x12 y19 w90 h20 , Where to search:
Gui, Add, Text, x335 y60 w150 h20 +Right vScanningText,
Gui, Add, Button, x452 y19 w30 h20 gSelectSearchDirectory, ..
Gui, Add, Button, x190 y49 w100 h30 gFindZeroByteFiles vFindFilesButton Default, Find zero byte files
Gui, Add, Button, x190 y49 w100 h30 gCancelScan vCancelScanButton, Cancel
GuiControl,Hide,CancelScanButton
Gui, Add, Checkbox, x10 y49 w170 vRecurse Checked%Recurse%,Scan inside sub-directories
Gui, Add, Edit, x102 y19 w340 h20 vSearchDirectory, %SearchDirectory%
Gui, Add, Progress, x10 y80 w475 h10 cBlue vProgressBar
Gui, Show, h100 w490, %NameOfProgram%
Menu,Menu1,Add,Copy path to clipboard,CopyToClipboard ;Used when rightclicking a found empty file.
Menu,Menu1,Add,Show in Explorer,HighlightInExplorer ;Used when rightclicking a found empty file.
Menu,Menu1,Add,Delete file/s,DeleteFile ;Used when rightclicking a found empty file.

;Hotkeys
Hotkey,IfWinActive,Empty files were found!
Hotkey,del,DeleteFile
Hotkey,IfWinActive,%NameOfProgram%
Hotkey,esc,GuiClose
Hotkey,IfWinActive,Empty files were found!
Hotkey,esc,2GuiClose
Hotkey,IfWinActive,Delete file confirmation
Hotkey,esc,DeleteMultipleFilesNo
Return

;Buttons
FindZeroByteFiles: ;Main function of the script
Gui 1:submit,nohide
GuiControl 1:,ProgressBar,0
IfNotExist,%SearchDirectory% ;Only run when searchdir actually exists.
{
			msgbox,48,Error!,The search directory was not found!
			return
		}
		;Blank out needed variables.
			CancelRequested = 0 ;Reset any cancel requests
			ZeroByteFilesFoundArray := Object() ; Create a blank array
			ZeroByteFilesFoundArrayExtension := Object() ; Create a blank array
			ZeroByteFilesCount = 0
			NumberOfFilesToScan = 0
			ListOfZeroByteFiles =
		GuiControl,Show,CancelScanButton
		GuiControl,Hide,FindFilesButton
		GuiControl,,ScanningText,Enumerating files..
		If Recurse ;Convert binary to R or blank for recursive function
			RecurseIntoSubdirectories = R
		Else
			RecurseIntoSubdirectories =
		Loop Files, %SearchDirectory%\*.*,%RecurseIntoSubdirectories% ;Count how many files there are to scan.
		{
			ifinstring,A_LoopFileFullPath,$RECYCLE.BIN ;Skip scanning the recycle bin
				continue
			if CancelRequested
				Break
			else
				NumberOfFilesToScan ++
		}
		if NumberOfFilesToScan = 1 ;Error out if there's nothing to do.
		{
			GuiControl,,ScanningText,No files in the scan folder.
			GuiControl,Hide,CancelScanButton
			GuiControl,Show,FindFilesButton
			return
		}
		else
		{
			GuiControl,,ScanningText,Scanning..
			Loop Files, %SearchDirectory%\*.*,%RecurseIntoSubdirectories%
			{
				ifinstring,A_LoopFileFullPath,$RECYCLE.BIN ;Skip scanning the recycle bin
					continue
				if CancelRequested
					Break
				else
				{
					PercentScanned := Ceil(A_Index / NumberOfFilesToScan * 100) ;Round up percentage value
					GuiControl,,ProgressBar,%PercentScanned%
					FileGetSize,FileSize,%A_LoopFileFullPath%
					if FileSize = 0
					{
						ZeroByteFilesCount ++
						ZeroByteFilesFoundArray.Insert(A_LoopFileFullPath)
						ZeroByteFilesFoundArrayExtension.Insert(A_LoopFileExt)
					}
				}
			}
			if CancelRequested
				{
					GuiControl,,ScanningText,Scan cancelled.
					GuiControl,Hide,CancelScanButton
					GuiControl,Show,FindFilesButton
					GuiControl,,ProgressBar,0
					return
				}
			If ZeroByteFilesCount
			{
				GuiControl,,ScanningText,Empty files were found!
				ListViewWidth = 980
				FileNameWidth := Ceil(ListViewWidth - 105 * 0.8 )
				ExtensionWidth = 80
				Gui 2: Add, ListView, altsubmit x10 y29 w980 h540 gSelectFoundZeroByteFile, Path|Extension
				Gui,2:default ;Needed to add items to list with LV_Add			
				Loop %ZeroByteFilesCount%
					{
						FilePath := ZeroByteFilesFoundArray[A_Index]
						stringreplace,FilePath,FilePath,\\,\,A ;Correct any double slashes
						FileExt := ZeroByteFilesFoundArrayExtension[A_Index]
						LV_Add("",FilePath,FileExt)
					}			
					Gui 2: Add, Text, x10 y9 w60 h20 , Empty Files:
					Gui 2: Add, Text, x400 y9 w250 h20 , Doubleclick an item to highlight it in Explorer.
					Gui 2: Add, Button, x9 y572 w150 h30 g2GuiClose, Close
					Gui 2: Add, Button, x842 y572 w150 h30 gDeleteFile, Delete selected file/s
					LV_ModifyCol(1,FileNameWidth)
					LV_ModifyCol(2,ExtensionWidth)				
					Gui 2: Show, h609 w1000, Empty files were found!
			}
			else
				GuiControl,,ScanningText,No empty files found.
			GuiControl,Hide,CancelScanButton
			GuiControl,Show,FindFilesButton
			return
		}
		
	DeleteFile:
		Gui,2:default ;Needed for LV_GetCount
		BUFFERSelectedEventInListView := SelectedEventInListView ;This variable gets changed the second the mouse gets clicked, we need to store its current value.
		BUFFERSelectedZeroByteFile := SelectedZeroByteFile ;This variable gets changed the second the mouse gets clicked, we need to store its current value.	
		NumberOfFilesToDelete := LV_GetCount("S")
		if NumberOfFilesToDelete = 1
		{
			if BUFFERSelectedZeroByteFile = Path ;If something went wrong with detecting the path, don't go any further with deleting.
				return
			Msgbox,36,Delete file confirmation,The following file will be deleted to the recycle bin:`n%BUFFERSelectedZeroByteFile%`n`nDo you wish to continue?
			ifMsgBox yes
			{
				filerecycle,%BUFFERSelectedZeroByteFile%
				LV_Delete(BUFFERSelectedEventInListView)
			}
		}
		else ;Make a list of what files were selected for deletion.
		{
			SelectedFilesForDeletionList = EMPTY ;Wipe the selected file list before we start our selections to it.
			RowNumber = 0  ; This causes the first loop iteration to start the search at the top of the list.
			Loop
			{
				RowNumber := LV_GetNext(RowNumber)  ; Resume the search at the row after that found by the previous iteration.
				if not RowNumber  ; The above returned zero, so there are no more selected rows.
					break
				LV_GetText(LvText, RowNumber)
				If SelectedFilesForDeletionList = EMPTY
					SelectedFilesForDeletionList = %LvText% ;First item doesn't need a linebreak/pipe character.
				else
					SelectedFilesForDeletionList = %SelectedFilesForDeletionList%|%LvText%
			}
			if SelectedFilesForDeletionList = EMPTY ;If we scanned everything selected and still came back empty, don't bother showing the UI.
				return
			Gui 3: Add, ListBox, x12 y39 w450 h140 HScroll, %SelectedFilesForDeletionList%
			Gui 3: Add, Text, x12 y19 w440 h20 , The following files will be deleted:
			Gui 3: Add, Text, x12 y189 w440 h20 , Do you wish to continue?
			Gui 3: Add, Button, x252 y219 w100 h30 gDeleteMultipleFilesYes +Default, Yes
			Gui 3: Add, Button, x362 y219 w100 h30 gDeleteMultipleFilesNo, No
			Gui 3: Show, h264 w477, Delete file confirmation
		}
		return

	DeleteMultipleFilesYes:
		Gui 3: Destroy
		Gui,2: default ;Needed to delete items from list with LV_Delete
			loop, % LV_GetCount("S")
				{
					LV_GetText(LvText, LV_GetNext(-1))
					LV_Delete(LV_GetNext(-1))
					filerecycle, % LvText
				}
		return

	DeleteMultipleFilesNo:
		Gui 3: Destroy
		return
		
	CancelScan:
		CancelRequested = 1
		return

	SelectSearchDirectory:
		FileSelectFolder,SelectedNewSearchFolder,SearchDirectory,3
		if SelectedNewSearchFolder ;Only update on user selected a new folder, not on a cancel.
		{
			SearchDirectory := SelectedNewSearchFolder
			GuiControl 1:,SearchDirectory,%SearchDirectory%
		}
		return		

	SelectFoundZeroByteFile: ;This acts more like a function. It's called anytime something is selected in the list of found files.
		Gui,2:default ;Needed for LV_GetText
		if (A_GuiEvent = "Doubleclick" or A_GuiEvent = "RightClick") ;If double or rightclick, method is slightly different.
		{
			LV_GetText(SelectedZeroByteFile, A_EventInfo) ;what file is currently selected in the listview.
			StringGetPos,SlashPos,SelectedZeroByteFile,\,R
			StringMid,SelectedZeroByteFileDirectory,SelectedZeroByteFile,0,SlashPos ;Trim the variable until we just have the directory
			SelectedEventInListView := A_EventInfo
			If A_GuiEvent = Doubleclick
				gosub,HighlightInExplorer
			else if A_GuiEvent = Rightclick
				 Menu,Menu1,Show
		}
		else
		{
			RowNumber = 0  ; This causes the first loop iteration to start the search at the top of the list.
			Loop
			{
				RowNumber := LV_GetNext(RowNumber)  ; Resume the search at the row after that found by the previous iteration.
				if not RowNumber  ; The above returned zero, so there are no more selected rows.
					break
				LV_GetText(SelectedZeroByteFile, RowNumber)
				SelectedEventInListView := RowNumber
			}
			return
}
return

;Subroutines
SetDefaultVariableValues:
SearchDirectory = %A_WorkingDir%
Recurse = 1
return

LoadSettings:
iniread,Recurse,ZeroByteFinderSettings.ini,Settings,Recurse
iniread,SearchDirectory,ZeroByteFinderSettings.ini,Settings,SearchDirectory
if (SearchDirectory = "ERROR" or SearchDirectory = "") ;Restore default if saved value was an error or blank
	SearchDirectory = %A_WorkingDir%
Return

SaveSettings:
gui 1:submit,nohide
IniWrite,%Recurse%,ZeroByteFinderSettings.ini,Settings,Recurse
IniWrite,%SearchDirectory%,ZeroByteFinderSettings.ini,Settings,SearchDirectory
return

CopyToClipboard:
clipboard = %SelectedZeroByteFile%
return

HighlightInExplorer:
Run,% "explorer.exe /e`, [color=Red]/n[/color]`, /select`," SelectedZeroByteFile
return

GuiClose:
gosub,SaveSettings
ExitApp

2GuiClose:
GuiControl 1:,ProgressBar,0
GuiControl 1:,ScanningText,
GuiControl 1:Hide,CancelScanButton
GuiControl 1:Show,FindFilesButton
Gui 2: Destroy
return

3GuiClose:
Gui 3: Destroy
return
		
Last edited by xcloudx01 on 07 Oct 2017, 23:11, edited 8 times in total.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Corrupted / 0 byte file finder

05 Oct 2017, 03:11

Great, thanks for sharing :thumbup:
It works well, but maybe add abillity to delete more than one file at a time. Also, your script will benefit from SetBatchLines,-1.

Cheers.
xcloudx01
Posts: 4
Joined: 05 Oct 2017, 00:27

Re: Corrupted / 0 byte file finder

05 Oct 2017, 03:16

I was a bit unsure actually on how to do that bit correctly. If you know how to correctly implement that I'd happily add it into the code :). I gave it a go but it'd only output the last thing selected.
Cheers i forgot about the batchlines thing. Added it in.
User avatar
rommmcek
Posts: 1475
Joined: 15 Aug 2014, 15:18

Re: Corrupted / 0 byte file finder

07 Oct 2017, 00:07

There may be a better way, but this one works for me:

Code: Select all

ifMsgBox yes
	{
		Gui,2:default ;Needed to delete items from list with LV_Delete
		loop, % LV_GetCount("S")
			{
				LV_GetText(LvText, LV_GetNext(-1))
				LV_Delete(LV_GetNext(-1))
				FileDelete, % LvText
			}
	}
Of course -multi option should be removed!
xcloudx01
Posts: 4
Joined: 05 Oct 2017, 00:27

Re: Corrupted / 0 byte file finder

07 Oct 2017, 07:52

That did the trick, thanks :D. Added it to the code, and also made it so the delete key works.
User avatar
rommmcek
Posts: 1475
Joined: 15 Aug 2014, 15:18

Re: Corrupted / 0 byte file finder

07 Oct 2017, 12:01

As a persistent keyboard user I added:

Code: Select all

	AppsKey::
		Gui,2: default ;Needed to delete items from list with LV_Delete
		if (LV_GetCount("S") > 0) {
			Click, 100, 100, 0
			Menu,Menu1,Show
			}
	return
But I'm sure, you will find more elegant solution!
xcloudx01
Posts: 4
Joined: 05 Oct 2017, 00:27

Re: Corrupted / 0 byte file finder

07 Oct 2017, 20:10

rommmcek wrote:As a persistent keyboard user I added:

Code: Select all

	AppsKey::
		Gui,2: default ;Needed to delete items from list with LV_Delete
		if (LV_GetCount("S") > 0) {
			Click, 100, 100, 0
			Menu,Menu1,Show
			}
	return
But I'm sure, you will find more elegant solution!
What line in the code did you add this to? I seem to be able to navigate the program okay using just the keyboard
User avatar
rommmcek
Posts: 1475
Joined: 15 Aug 2014, 15:18

Re: Corrupted / 0 byte file finder

07 Oct 2017, 21:45

I just appended it to the end of your code. (AppsKey did not show menu for me in Gui2 when some lines were selected)
Besides, I find useful:

Code: Select all

	~Esc::
	2GuiClose:
		GuiControl 1:,ProgressBar,0
		GuiControl 1:,ScanningText,
		...
Bye!

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 190 guests