# Solved: Capturing Command Line Defragmentation Analysis Report



## scrfix (May 3, 2009)

I believe I already know the answer to this however 
I would like to be able to detect what the percent file fragmentation is and if it is greater than 15% then automatically defragment the drive.

When utilizing the defrag.exe in the Vista command line, I utilize:
defrag %systemdrive% -a -v
It takes between 2 - 6 minutes and then reports back the following Analysis report.


```
Windows Disk Defragmenter
Copyright (c) 2006 Microsoft Corp.
Analysis report for volume C: OS
    Volume size                         = 137 GB
    Cluster size                        = 4 KB
    Used space                          = 77.03 GB
    Free space                          = 59.95 GB
    Percent free space                  = 43 %
File fragmentation
    Percent file fragmentation          = 0 %
    Total movable files                 = 334,274
    Average file size                   = 276 KB
    Total fragmented files              = 235
    Total excess fragments              = 898
    Average fragments per file          = 1.00
    Total unmovable files               = 83
Free space fragmentation
    Free space                          = 59.95 GB
    Total free space extent             = 706
    Average free space per extent       = 87 MB
    Largest free space extent           = 32.20 GB
Folder fragmentation
    Total folders                       = 37,839
    Fragmented folders                  = 41
    Excess folder fragments             = 249
Master File Table (MFT) fragmentation
    Total MFT size                      = 331 MB
    MFT record count                    = 334,890
    Percent MFT in use                  = 98
    Total MFT fragments                 = 18
    Note: On NTFS volumes, file fragments larger than 64MB are not included in
he fragmentation statistics
    You do not need to defragment this volume.
```
Is it possible to capture this report
search through the report for the Percent file fragmentation
compare to see if it is greater than 15%
then execute the following commands:
defrag %systemdrive% -w -f

I would think the only way to do this is a for statement with a findstr however I am unsure as to whether the time frame where the report comes back to me is going to be an issue plus that is a lot to search.

I am thinking something to the following However I am not sure what to put inside the quotes now am I sure how to store the output to a variable I can search.


```
FOR /F "TOKENS=* DELIMS=Percent file fragmentation          =  " %%A IN ('%VAR-HERE%^|FIND /I "NOT-SURE"') DO SET VAR-HERE=%%A
```
Is this possible?


----------



## ghostdog74 (Dec 7, 2005)

if you have Gawk for windows

```
BEGIN{
 FS="="
}
/Percent file fragmentation/ && ( $2+0 )> 15 {
	print "over 15%"	
	cmd = "defrag "ENVIRON["SystemDrive"]" -f"
	print cmd
	system(cmd)
        exit	
}
```
save as myscript.awk and on command line

```
e:\test> defrag c: -a -v | gawk -f test.awk
```


----------



## scrfix (May 3, 2009)

GhostDog,

Thanks for the reply. I am attempting to do this without having to install 3 party software on the computer. I have various amounts of computers that come and go and I cannot install software on all of them.

I was thinking about going to an external file such as a text file and then reading that text file and going from there. Just not sure how to accomplish that within the batch language.


----------



## TheOutcaste (Aug 8, 2007)

You can't use a string as a delimter, it will use each individual letter as a delimiter.
This will do the trick:

```
For /F "Tokens=1,2 Delims==^%%" %%A In ('defrag %systemdrive% -a -v^|Findstr /I /C:"Percent File Fragmentation"') Do Set /A _PercentFrag=%%B
If %_PercentFrag% GTR 15 defrag %systemdrive% -w -f
```
Jerry


----------



## scrfix (May 3, 2009)

Jerry,

I am afraid to ask how you learned all of this. I searched EVERYWHERE looking for how I would store that into a variable of something. I even found a website that told me how to do an array in a batch and I was getting ready to attempt that.

Thanks again. I am sure I will have more questions. I am actively attempting these items that you have taught me and I am sure that I am getting the hang of some things. It is the FOR statement and yes I have read the /? for it over and over again. It still has me stumped. I think as i break down a lot of these different for statements I will start to understand it better.

I just attempted to run the defragment script above. It locked up my system for 15 minutes now. I cannot do anything at all. Should I have something else in there. I already know that the defragment in Vista sucks pretty badly but with the FOR statement it really hates it. I have had the lid closed on my computer for the last 5 minutes hoping that it will go into standby on its own and I can restart it because I have items that are not saved however the fan is still running.

On my XP box the defrag -a -v prints out a report immediately. Took less than 2 seconds. On my Vista box, it takes around 2 - 6 minutes to print that same report.

Ending result: I had to shut the computer down. It is however taking an unusual long time to boot up now however. It is getting there however. Back to the drawing board.

Is there another way without that effect happening?


----------



## Squashman (Apr 4, 2003)

Learn by doing and understanding the stuff people help you with here. Once you learn all the stuff you can do in a For Loop that will open up alot of things for you. Once you get the basics down you can pretty much refer to the help file or examples you find online to write your batch files.

I use a piece of sofware on the mainframe at work that was written in assembler in 1993. It still works awesome today. Once I learned the basics of each parameter card, I could then reference the manual on how to expand that to more complex programming logic.

You already have some computer experience you just need to build on that. Alot of times I end up referencing stuff I learned on the Mainframe to my PC stuff and vice versa.


----------



## scrfix (May 3, 2009)

I am working on it. I know a lot about the IF statements and a lot of other things that I have learned here and other places however the FOR statement just eludes me. I am sure I will pick it up.

There are just things that I have read and read and still do not understand such as the token. I thought a * would include everything however I just learned from Jerry that this will include only the first word, etc etc etc.

Hey,

Is there a better way to write the following so that it does not lock up the system?


```
For /F "Tokens=1,2 Delims==^%%" %%A In ('defrag %systemdrive% -a -v^|Findstr /I /C:"Percent File Fragmentation"') Do Set /A _PercentFrag=%%B
If %_PercentFrag% GTR 15 defrag %systemdrive% -w -f
```
*Here is what I understand (and do not understand) about it:*
1. (I am not sure what Tokens 1,2 do for this. Guessing that they look at the first two words? If that is correct then they would be looking at Windows Disk)
2. Delims=^%% (Looks for %, I am presuming)
3. %%A grabs the items whatever tokens 1,2 looks at
4. 'defrag %systemdrive% -a -v^|Findstr /I /C:"Percent File Fragmentation (Run the command, look for Percent File Fragmentation in %%A
5. Do Set /A _PercentFrag=%%B (Do set the variable equal to what you found and return it as a number.
6. If %_PercentFrag% GTR 15 defrag %systemdrive% -w -f (If the variable is greater than 15 then run the next command.

What do those first two items do?
Is there something else I need to include so that my Vista system does not lock up on me.


----------



## Squashman (Apr 4, 2003)

I know what you mean about the Tokens and For loop. That was the hardest thing for me to transition to and I have a Pascal and Fortran programming background, plus I did alot of BASH shell scripting on Linux.
1)Think of tokens as something that help you assign your variables. You want two variables to come out of every line of your input. But of course you need a delimiter to define what is going to be assigned to those variables. Tokens are directly related to the %%A and %%B. Token 1 goes to %%A and Token 2 goes to %%B. If you needed 4 variables you would Tokens=1-4. So you would have variables %%A to %%D. Those variables will be populated based on your delimiters you define. If you do not define a delimiter the FOR loop assumes you want to use a TAB and SPACE for the delimiter.
2) Jerry is assinging the delimeters to be an EQUALS sign and a PERCENT sign. If he didn't put thePERECENT sign as a delimiter your %%B variable would equal 15% instead of 15.
3) %%A get assigned whatever is before the first Delimiter is. In this case the first delimiter it finds is the EQUALS sign so %%A gets assigned "Percent File Fragmentation". Now %%B becomes the second Token and gets assigned whatever is after the EQUALS sign. So it gets assigned the number value after the equals sign and since he using a PERCENT symbol as a delimiter it only gets the number value and not the percent symbol.


----------



## Squashman (Apr 4, 2003)

Now what will really blow your mind is if you have Tokens=2,3 your the For Loop will assign whatever is after the First Delimiter to %%A. In this case the number would get assigned to %%A and nothing would get assigned to %%B.


----------



## TheOutcaste (Aug 8, 2007)

Looks like Squashman did a nice explanation as I was typing this.:up:
Here's my version anyways.

A For loop looks at _each_ line of text generated by what ever is in the *In (...)* part.
It splits the line of text into pieces (tokens) using the specified delimiters.
So the command (Number 4) is run, Findstr restricts the output to one line of text containing Percent File Fragmentation, and that is what is returned to the For loop:

```
[FONT=monospace]
    [/FONT]Percent file fragmentation          = 0 %
```
I'm using _two_ delimiters (Delims==^%%), the Equals sign and the Percent sign. The percent sign has to be doubled in a batch file, and the caret escapes it so it won't be mistaken for the start of a variable to be expanded.
I included the percent sign as a delimiter to easily remove the percent symbol at the end of the line.
This will split the line into these two parts (>< symbols added to show the spaces):


> Percent file fragmentation <
> 0 <
Tokens=tells the For loop which pieces (tokens) to get from the parsed line. 1,2 means get the first and second tokens;%%A=#1 and %%B=#2 _from each line_. (This will also work if you use Tokens=2, then %%A will be given the value of token #2). The Findstr part limits the output to just one line, so all the other lines aren't split by the For loop, they are ignored.
I started with the tokens=1,2 because I was initially going to use an If statement to find the *Percent file fragmentation* part in %%A, then assign the %%B token to the variable, then realized I'd still have to remove the leading/trailing spaces from %%A to do the match. So decided to use Findstr to find the line.
Just didn't bother to change it to tokens=2.
I used Set /A rather than just Set because it has the side benefit of removing the leading and trailing spaces around the 0.

I don't know why it would lock the system.
Defrag has to be run from an Admin command prompt. If you run in a normal prompt, it should just display an error, then continue with the If statement. _PercentFrag would be undefined (unless it has a value from a previous run) so the If statement should fail and abort the batch file. If it does have a value and it's over 15, it will run Defrag, but either case shouldn't lock the system

Mine took about 3 minutes then told me it was 3% fragmented (Vista Ultimate x86 running in VPC), and about 5 minutes and 4% on my laptop running Vista Home Premium x64. Neither one locked up.

You might try directing the output to a temp text file, then read the text file in the For loop to see if that makes a difference:

```
>DFreport.txt defrag %systemdrive% -a -v
For /F "Tokens=2 Delims==^%%" %%A In ('type DFreport.txt^|Findstr /I /C:"Percent File Fragmentation"') Do Set /A _PercentFrag=%%A
```
If you can get Task Manger open when it freezes like that, you can end the cmd.exe process.

Note that this won't work on XP, the wording in the report is different. XP lists 3 different fragmentation percentages, so you'd have to check which OS is running and modify the Findstr string accordingly. You'd have to pick which one to check. Here's what my XP system displays:

```
Volume fragmentation
    Total fragmentation                 = 2 %
    File fragmentation                  = 5 %
    Free space fragmentation            = 0 %
```
Though if you search for just *file fragmentation*, it will work for both Vista and XP.


----------



## scrfix (May 3, 2009)

Squashman,

That was a perfect explanation of that. I believe I at least semi-understand the %%A and %%B when utilizing tokens=1,2. I will play around with that and test that when I get back home.

I found out that if I just utilize the -a instead of the -a -v I can still get the percent file fragmentation with a smaller report. It still takes 2+ minutes to output. I wish it was faster but that is Vista I guess.

Jerry,

I will read your explanation tonight when I get back home.


----------



## scrfix (May 3, 2009)

I found out why it was locking up on me. I went into the task manager and had around 30-40 findstr.exe and 30-40 cmd.exe commands running at the same time. My CPU also maxed out to 100% while that command line was running. As soon as I took away the -v I no longer had multiple findstr.exe commands running but still had at least 20 cmd.exe commands running in the task manager and the CPU was still maxed out at 100%.


----------



## scrfix (May 3, 2009)

I am going to mark this as solved until I can get back to it this weekend. If I have other questions I will unsolve it.

Thanks for everything and all of the explanations.


----------



## scrfix (May 3, 2009)

For anyone that is looking for a good website to see what the for loop can do and other commands associated with it, they can go here: http://www.ss64.com/nt/for_f.html

It does appear that this is for an earlier version of the FOR command however the basics are there. It explains tokens, skips and provides examples of usage.


----------

