defrag script for sysinternal contig

Page 1 of 5 123 ... LastLast

  1. Posts : 250
    Windows 10 22H2
       #1

    defrag script for sysinternal contig


    Hi,

    I'm writing a batch for defrag file with the sysinternal contig.

    I need a hand to develop and test it better. For now it performs only the analysis and is developed for the "Italian" language but I would like to make it more flexible.

    Code:
    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    :: Edefrag - By Einstein1969
    :: 
    :: Ver 0.0.3 13/07/2021
    ::
    :: You need download sysinternal contig (32bit) and copy in "windows\system32" folder
    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    @echo off 
    (Fsutil Dirty Query %SystemDrive%>Nul)||(PowerShell start """%~fn0""" -verb RunAs & Exit /B)
    
    setlocal EnableDelayedExpansion & if "%1" == "wait" goto :wait
    
    set "Disk=C"
    rem set/p "Disk=Insert Disk Letter and press Enter (default=!Disk!). Es. 'C' >"
    
    set "minfrags=4"
    
    rem italian
    set "string1=Dimensioni allocate"
    
    chcp 1252
    
    echo Searching for fragmented files.
    
    cd %TMP%
    
    ( 
      del stop.tmp 2>nul
      contig -a -s "%Disk%:\*.*" | find "fragments" >Edefrag.log
      type nul: >stop.tmp
    ) | %0 wait
    
    echo(
    echo Analyze the files with minimum !minfrags! frags.
    
    set f=0
    for /f "tokens=*" %%F in ('more Edefrag.log') do (
      call set "s=%%F"
      set "s=!s:*...=!"
      set "s=!s:~0,-10!"
    
      for %%A in ("!s: =\!") do set "fr=%%~nA"
      if not defined fr echo [!s!] Error in frags number. & pause & goto :eof
    
      if !fr! geq !minfrags! (
    
         set "$=!fr!fedcba9876543210"
         set/a l=0x!$:~16,1!+1, f+=1
         for %%A in ("!l!") do set "fn=!s:~,-%%~A!"
         set "fn=!fn:~,-7!"
         if not exist "!fn!" echo [!fn!] Error, file not found. & pause & goto :eof
    
         for %%A in ("!fn!") do set "t=%%~aA"
         if not defined t echo [!fn!] [!fr!] Error in attributes. & pause & goto :eof
    
         if "!t:~0,1!"=="d" (set "t=d") else set "t=f"
     
         set "dim="
         if "!t!"=="f" (
           for /f "tokens=4*" %%c in ('fsutil file layout "!fn!" ^| find "!string1!"') do if not defined dim set "dim=%%d" 
           rem set "dim=!dim:.=!"
         ) else set "dim=NA"
         set "f_=   !f!"
         echo !f_:~-4! [!t!] !fr! frags [!fn!] Dim=!dim!
      ) 
    
    )
    pause
    goto :eof
    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    :wait
    
    rem echo %2 is running...
    
    for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
    
    set "s=|/-\"
    
    set LN=0
    for /L %%N in (0) do (
    
      ping -n 2 127.0.0.1 >nul
    
      set /a "N=(N+1) %% 5"
    
      if !N! equ 0 (
    
        if !LN! equ 0 (
           for /f %%L in ('FIND /V /C "" ^< Edefrag.log') do set /A LN=%%L, LLN=%%L-1
        ) else (
           for /f %%L in ('More Edefrag.log +!LN! ^| FIND /V /C ""') do set /A LN+=%%L, LLN=LN-1
        )
      
        set "v="
        if !LN! gtr 0 for /f "tokens=*" %%S in ('more Edefrag.log +!LLN!') do call set "v=%%S"
    
        if defined v set "v=!v:*...=!" & set /P "=_!CR!    Found !LN! elements: !v:~0,60!...                                       !CR!" < nul
      )
    
      set /P "=_!CR![!s:~0,1!]" < nul
    
      set "s=!s:~-3!!s:~0,1!"
    
      if exist stop.tmp echo(&exit
    
    )
    goto :eof
    :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    EDIT: update script to version 0.0.2, fixed an error on retrive allocate dimension of file
    EDIT: update script to version 0.0.3, fixed some error and make faster.
    Last edited by einstein1969; 13 Jul 2021 at 15:28. Reason: update script to version 0.0.3
      My Computers


  2. Posts : 745
    Windows 10/11
       #2

    I recommend that you first rewrite your script in PowerShell. Batch files that use a lot of variables, If statements, and for loops, are ugly and hard to follow. If you write this script in PowerShell, it will be MUCH easier to understand and maintain.

    However, if you have a very specific issue with your batch file, please state what the issue is and I'm sure someone here will help figure out what's wrong.
      My Computer


  3. Posts : 250
    Windows 10 22H2
    Thread Starter
       #3

    LesFerch said:
    I recommend that you first rewrite your script in PowerShell. Batch files that use a lot of variables, If statements, and for loops, are ugly and hard to follow. If you write this script in PowerShell, it will be MUCH easier to understand and maintain.

    However, if you have a very specific issue with your batch file, please state what the issue is and I'm sure someone here will help figure out what's wrong.
    I'm not very familiar with powershell. I could try with your help. Is there anyone who can help me with the powershell rewrite? The first part of the script generates the list of fragmented objects. How can I do this in powershell?
      My Computers


  4. Posts : 745
    Windows 10/11
       #4

    I can get you started with a PowerShell version, but what's the end goal? What are you trying to achieve with the script?
      My Computer


  5. Posts : 250
    Windows 10 22H2
    Thread Starter
       #5

    The idea is to defragment the disks faster and for some particular situations. All the free defragmenters I have tried always have limitations and choose what to defragment automatically.
      My Computers


  6. Posts : 745
    Windows 10/11
       #6

    Okay, let's turn those goals into a series of steps that we can program. If you run contig -s C:\*.* it will try to defragment every file. It will, of course, skip files that are open and in use or otherwise locked from being messed with. Are you wanting to somehow have it defragment only files that have reached a certain threshold of fragmentation?

    I see that you're running contig -a -s "!Disk!:\*.* and then wanting to do something with that output. If you can provide step by step what you want the script to do, I can translate that into PowerShell code, but I can't read your mind. I could spend more time trying to figure out exactly what your batch file is doing already, but I'd rather have you provide the specifications. That will result in better code.
      My Computer


  7. Posts : 250
    Windows 10 22H2
    Thread Starter
       #7

    For example, I often defragment internal and external disks with sparse and / or compressed files. Sometimes with tens of thousands of fragments per file. Even extreme situations where the disk is very full.

    I upgraded to version 0.0.3. I have speeded up and made the process of searching for fragmented objects more interactive

    - - - Updated - - -

    LesFerch said:
    Okay, let's turn those goals into a series of steps that we can program. If you run contig -s C:\*.* it will try to defragment every file. It will, of course, skip files that are open and in use or otherwise locked from being messed with. Are you wanting to somehow have it defragment only files that have reached a certain threshold of fragmentation?

    I see that you're running contig -a -s "!Disk!:\*.* and then wanting to do something with that output. If you can provide step by step what you want the script to do, I can translate that into PowerShell code, but I can't read your mind. I could spend more time trying to figure out exactly what your batch file is doing already, but I'd rather have you provide the specifications. That will result in better code.
    Yes, I would like to choose what to defrag, the order of defragmentation and also the fastest method of defragmentation (copy, defrag with contig or microsoft defrag). I've already sketched out some ideas. For example I am starting to defragment in order to choose the higher rate of fragments per second removed.
      My Computers


  8. Posts : 745
    Windows 10/11
       #8

    I was really hoping you could provide high-level pseudo code of what you're doing (or trying to do). I don't want to have to reverse engineer your batch script.

    See:
    Pseudocode Examples
      My Computer


  9. Posts : 250
    Windows 10 22H2
    Thread Starter
       #9

    A first simple formula is for example to sort the files to be defragmented according to the ratio: file size / number of fragments

    - - - Updated - - -

    LesFerch said:
    I was really hoping you could provide high-level pseudo code of what you're doing (or trying to do). I don't want to have to reverse engineer your batch script.

    See:
    Pseudocode Examples
    Don't worry, I really don't recommend you do the reverse as it would take a long time. I'll explain in natural language what it does. I will try to write it in pseudocode if necessary. Give me some minutes.

    - - - Updated - - -

    I have added pseudo code to version 0.0.4

    Code:
    This script do:
    
    1) It collects all the information you need to be able to choose the best way to defragment.
    
       1a) Run the script as administrator (required by contig, fsutils and defrag)
    
       1b) Use the command:  
              contig -a -s "% Disk%: \ *. *" | find "fragments"
           to get the list of fragmented objects.
    
       1c) Analyze the files with minimum 4 frags. four is editable parameter (for faster execution)
           
       1d) collects the object type file/dir
    
       1e) the size actually allocated by the objects with the command:
               fsutil file layout 
           
       1f) Extracts the number of fragments and the name of the object found from the previous contig command
    - - - Updated - - -

    There are several problems I had to solve:

    The contig command has a particular output.
    It inserts an isolated CR character on its output lines.

    It also seems to use codepage 1252 for file name output.

    Some files with unicode characters or other codepage (ex cirillic are not detected well)

    - - - Updated - - -

    these are 2 screen shoot of two phase of running

    search phase:
    defrag script for sysinternal contig-search.png

    analyze phase:
    defrag script for sysinternal contig-analyze.png
      My Computers


  10. Posts : 745
    Windows 10/11
       #10

    Thanks for the detailed breakdown. PowerShell is definitely the way to go.

    But I have to ask a bigger question... Is there really much benefit to be gained by defragmenting? 30 years ago when I defragmented a hard drive, it made a noticeable performance improvement. Today, I doubt it will help much. With my 9 year old laptop, I found that a complete wipe and fresh install of Windows 10 (which would naturally result in minimal fragments) made only a small improvement to overall performance. What made a HUGE difference in performance was replacing my HD with an SSD. If I were seeking any further improvements (short of buying a new computer) I would also look at increasing RAM (if possible), so disk accesses are minimized.

    There's also the issue that defragmenting an SSD is unnecessary (Should You Defrag an SSD? | Crucial.com) and uses up some of the flash memory's finite write cycles.

    Anyhow, assuming this will be targeted to an HD and not an SSD, the programming looks interesting. I'll have a go and get back to you.
      My Computer


 

  Related Discussions
Our Sites
Site Links
About Us
Windows 10 Forums is an independent web site and has not been authorized, sponsored, or otherwise approved by Microsoft Corporation. "Windows 10" and related materials are trademarks of Microsoft Corp.

© Designer Media Ltd
All times are GMT -5. The time now is 11:11.
Find Us




Windows 10 Forums