fsutil 8dot3name: the files strip silently skips

Every file created on an NTFS volume with 8.3 name creation left on gets two names, not one. There is the long name a person reads, and there is a generated short name of at most eight characters, a dot and three more, which almost nothing displays. It is invisible until it is not: an installer records it, a wildcard matches it, or a directory with a great many files in it gets slower, because NTFS has to look up the short names already in it every time a file is created there.

fsutil 8dot3name is the one built in command that covers the whole of that problem. It reports whether a volume is still creating short names, it scans a directory tree for registry keys that point at the ones already there, and it removes them. The three are separate operations and doing one of them does not do the others, which is the first thing that trips people up.

The existing fsutil guide on this site covers volumes, sparse files and fsutil fsinfo ntfsinfo. This page is about the subcommand that page leaves out, and about the rule inside it that decides, without telling you, which files keep their short names anyway.


Quick answer

Three steps, in the order that leaves nothing behind. Run all of them from an elevated prompt.

rem 1. what is this volume doing right now
fsutil 8dot3name query D:

rem 2. stop new short names being created on D: only
fsutil 8dot3name set 2
fsutil 8dot3name set D: 1

rem 3. remove the short names that already exist, test first
fsutil 8dot3name strip /t /s /v D:\Shares\Dept
fsutil 8dot3name strip /s /l C:\temp\strip.log D:\Shares\Dept
Order matters: Setting the policy first means no new short name is created while the strip is running. Stripping first leaves you removing names from files that are still being given them.

Before the first example

Four things have to be true before any of the commands above are worth running, and none of them takes more than a line or two.

One. The prompt has to be elevated. Microsoft states the requirement on the fsutil page itself: “You must log on as an administrator or a member of the Administrators group to use fsutil”.

rem High Mandatory Level in the output means the prompt is elevated
whoami /groups | findstr /i "High Mandatory Level"

Two. You need to know whether the volume you are about to change is the system volume, because one of the four settings treats it differently. echo %SystemDrive% answers it and does not depend on drive letters staying where you remember them.

echo %SystemDrive%
fsutil fsinfo volumeinfo D:

Three. Read the machine wide default before you change it, so you can put it back. It is a single registry value and reg query reads it without any of the fsutil spellings getting involved.

reg query "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" /v NtfsDisable8dot3NameCreation

Four. Back the tree up. The fsutil 8dot3name page carries an explicit warning that removing short names without fixing the registry keys that point at them can break applications, including their uninstallers, and it recommends backing up the directory or volume first. robocopy is the cheap way to do it.

robocopy "D:\Shares\Dept" "E:\Backup\Dept" /E /COPY:DAT /R:1 /W:1
There is no undo: Nothing in fsutil 8dot3name strip restores a short name once it is gone. The only way back is the backup, or fsutil file setshortname on each affected file by hand.

Example 1: read what the volume is doing today

The problem: a file server has been running for years and nobody knows whether short name creation was ever turned off, or turned off for the whole machine, or turned off for one volume.

The solution: fsutil 8dot3name query with a volume path reports that volume, and without one reports the machine wide default.

rem the default that applies to every volume
fsutil 8dot3name query

rem the state of one volume
fsutil 8dot3name query D:

rem a volume with no drive letter, by GUID
fsutil 8dot3name query volume{928842df-5a01-11de-a85c-806e6f6e6963}
No output is shown on this page, deliberately: Microsoft documents no output for any fsutil 8dot3name subcommand. The reference page has an Examples section and every entry in it is a command with nothing after it. Rather than invent a capture, this page describes what each command answers and leaves the text on your own screen to speak for itself.

Example 2: find what points at a short name before you strip

The problem: the tree is a software share and something in it was installed years ago by an installer that wrote a short path into the registry. Removing the short names would leave that key pointing at nothing.

The solution: fsutil 8dot3name scan is the read only half of fsutil 8dot3name strip. It walks the directory and reports the registry keys that reference the short names it finds, and it changes nothing at all.

rem one directory only
fsutil 8dot3name scan D:\Shares\Apps

rem the whole tree, echoing the log to the console as well
fsutil 8dot3name scan /s /v D:\Shares\Apps

rem the whole tree, into a log file you choose
fsutil 8dot3name scan /s /l C:\temp\8dot3-scan.log D:\Shares\Apps

What scan cannot tell you is whether a key that points at a short name still matters. It reports the keys; deciding which of them belong to software that is still installed is the part that takes an afternoon. Run it early, because the list is usually shorter than the fear of it.

Without /s it is one level: /s is documented as applying the operation to the subdirectories of the path. Leave it off and a scan of the share root reports on the handful of loose files sitting in it and nothing else, which reads exactly like a clean result.

Example 3: strip the short names from one tree

The problem: the scan came back clean, or the keys it found have been dealt with, and the short names now have to go.

The solution: fsutil 8dot3name strip removes them. It has a test mode, and the test mode is the whole reason this is a two step operation rather than one.

rem /t runs everything except the removal
fsutil 8dot3name strip /t /s /v D:\Shares\Dept

rem the real thing, with a log file you can find again
fsutil 8dot3name strip /s /l C:\temp\8dot3-strip.log D:\Shares\Dept

The documented behaviour of /t is that all operations except the actual removal are performed, which is what makes it a rehearsal rather than a guess. It is also documented as the way to discover which registry keys point at files using short names, so it overlaps with scan rather than replacing it.

On a share of any size the test run is not a formality. It is the only point at which the list of files that will be changed, and the list of registry keys that reference them, exists in one place while nothing has happened yet. Read it, then run the same line without /t.

SwitchWhat it doesWhen to leave it off
/tTest mode. Everything except the removal.Only on the second run, once the test output has been read.
/sApply to the subdirectories as well.When you genuinely mean one directory.
/vEcho everything written to the log to the console too.In a scheduled job, where the log file is the record.
/lWrite to a log file you name.Never, in practice. See the note below.
/fRemove the names even where registry keys point at them.Almost always. See Boundary 5.
The default log file name is hard to predict: With no /l, the documented default is a file under %temp% whose name embeds a GMT timestamp in parentheses. It is findable, but it is not something a scheduled task can predict, so name the log yourself.

Example 4: stop new short names from being created

The problem: stripping a tree today does nothing about the files created tomorrow.

The solution: fsutil 8dot3name set writes the creation policy. There is a machine wide form and a per volume form, and they look almost identical.

rem machine wide: disable everywhere
fsutil 8dot3name set 1

rem machine wide: decide per volume from now on
fsutil 8dot3name set 2

rem per volume: disable on D: only. Needs the default to be 2 first
fsutil 8dot3name set D: 1
No restart: Of the seventeen parameters documented in the fsutil behavior table, fourteen carry the sentence “You must restart your computer for this parameter to take effect”. disable8dot3 is one of the three that does not. The count is in the measurement below.
parameters documented in the fsutil behavior table : 17
rows that say you must restart                     : 14
rows that do not                                   : 3

the ones that do not:
    disable8dot3
    symlinkevaluation
    disabledeletenotify

Example 5: list the files strip will leave alone

The problem: strip reports what it did, after it has done it. What you want before you start is the list of files it is going to walk past.

The solution: the rule it uses is documented and it is arithmetic, so PowerShell can apply it to the same tree first. A short function keeps the threshold in one place.

function Get-SkippedShortName {
    param(
        [Parameter(Mandatory)][string]$Path,
        [int]$Limit = 260
    )
    Get-ChildItem -LiteralPath $Path -Recurse -File -ErrorAction SilentlyContinue |
        ForEach-Object {
            [pscustomobject]@{
                PathLength = $_.FullName.Length
                Skipped    = $_.FullName.Length -gt $Limit
                FullName   = $_.FullName
            }
        }
}
$Share   = 'D:\Shares\Dept'
$Archive = 'D:\Shares\Departments\Archive\Retained until 2031 under legal hold\Migrated from OLDFS01 during the 2026 file server consolidation'

'{0,-6}{1,-9}{2,-9}{3,-9}{4}' -f 'root', 'files', 'removed', 'skipped', 'longest'
'-' * 48
foreach ($r in @($Share, $Archive)) {
    $rows = @(Get-SkippedShortName -Path $r)
    $skip = @($rows | Where-Object Skipped)
    $max  = ($rows | Measure-Object PathLength -Maximum).Maximum
    '{0,-6}{1,-9}{2,-9}{3,-9}{4}' -f $r.Length, $rows.Count, ($rows.Count - $skip.Count), $skip.Count, $max
}

Run the function over the same 135 files under two different share roots and it separates them cleanly. $Share is a normal share. $Archive is what the same tree looks like after somebody moved it under an archive path during a server consolidation.

root  files    removed  skipped  longest
------------------------------------------------
14    135      135      0        147
130   135      123      12       263
Same files, different answer: Nothing about the 135 files changed. Only the path above them did, and twelve of them stopped being strippable. That is Boundary 3, and it is the only reason this function is worth having.

The same function answers the next question too, which is how much of the path has to go. The rule is a threshold, so the shortfall is arithmetic rather than a judgement call.

$over = @(Get-SkippedShortName -Path $Archive | Where-Object Skipped)

if ($over.Count) {
    $worst = ($over | Measure-Object PathLength -Maximum).Maximum
    '{0,-36}{1}' -f 'share root', $Archive.Length
    '{0,-36}{1}' -f 'files strip would skip', $over.Count
    '{0,-36}{1}' -f 'longest of them', $worst
    '{0,-36}{1}' -f 'characters to remove from the root', ($worst - 260)
}
share root                          130
files strip would skip              12
longest of them                     263
characters to remove from the root  3

Three characters. One folder in that path renamed slightly shorter and every one of the twelve comes back inside the rule. That is the whole remedy, and Boundary 3 shows it working.

Do not name a property Count: The function returns PathLength and Skipped rather than anything called Count or Length. PowerShell gives every array and every scalar a Count of its own, so a property by that name works right up until the pipeline returns more than one object.

The same question under three different spellings

Three commands read the 8.3 creation setting and two of them are the same thing. The third is not, and the difference is the one that matters.

SpellingWhat it readsSees the per volume flag
fsutil 8dot3name query D:The effective setting for that volume.Yes
fsutil behavior query disable8dot3 D:The same setting. Each reference page points at the other as an alternative.Yes
reg query ... NtfsDisable8dot3NameCreationThe machine wide default only. This is the odd one out.No

The first two are documented as interchangeable: the fsutil 8dot3name page says the behaviour can also be queried with the behavior subcommand, and the fsutil behavior page says the same thing in reverse. The third reads the registry value that fsutil 8dot3name set writes, which is a different and smaller fact.

The registry value is not the answer for a volume: When the machine wide default is 2, the value says only that the decision has been delegated. A monitoring check that reads the registry key and reports “short names disabled” is wrong on every volume of every server configured that way.

Seeing a short name, and the wildcard that matches it

dir /x is the switch that shows both names. The display is the long list format with the short name inserted before the long one.

dir /x D:\Shares\Dept

The shape below is the one Microsoft’s own dir reference uses, with the file names replaced by names from the example share used throughout this page.

 Directory of D:\Shares\Dept

29/09/2026  09:14    <DIR>          .
29/09/2026  09:14    <DIR>          ..
29/09/2026  09:12              4096 ANNUAL~1.DOC Annual report 2026 final signed copy.docx
29/09/2026  09:12              2048              Notes.txt

Microsoft’s own example behaves the same way: one file carries a name in the short name column and the other has nothing there at all. Notes.txt already fits in eight characters, a dot and three, so there is nothing for NTFS to shorten.

The asterisk matches the short name too: The dir reference states it plainly: the asterisk wildcard always uses short file name mapping. Its worked example has a directory holding t.txt2 and t97.txt, where dir t97\* returns both files because the wildcard matches t.txt2 through its short name T97B4~1.TXT. It adds that del t97\* would delete both. That is the strongest practical argument for removing short names from a share that scripts write to.

Boundary 1: the same digit means two different things

fsutil 8dot3name set 1 and fsutil 8dot3name set D: 1 differ by one argument and mean unrelated things. The first writes a machine wide registry value. The second sets a flag on one volume, and does nothing useful unless the machine wide value is already 2.

The line in fullWhat the 1 isWhat it changes
fsutil 8dot3name set 1A default valueThe registry value that applies to every volume
fsutil 8dot3name set D: 1A per volume flagOne volume, and only while the default is 2
The argument that disappears: A wrapper script that passes its arguments straight through is the usual way this goes wrong. Called with a volume and a value it disables one volume. Called with the value alone it silently reconfigures the whole machine. Both forms are valid, so neither reports a problem.

The documentation is explicit about the dependency: the default must be set to 2 before short name creation can be enabled or disabled for a specified volume.

The order that follows from that is fsutil 8dot3name set 2 and then fsutil 8dot3name set D: 1, and it is worth writing into the runbook rather than remembering. Run them the other way round and the second command lands on a machine whose default no longer delegates anything, so the flag it writes sits on the volume unread.

Setting the default to 2 does not change any volume: fsutil 8dot3name set 2 only moves the decision. Until a per volume flag is written, no volume has been told anything, which is why the two commands belong together in the same change window.

Boundary 2: value 3 is the odd one out

The machine wide default takes four values. Three of them describe every volume on the machine in the same way. The fourth does not, and it is the one a reader skims past.

ValueDocumented meaningSame answer for every volume
0Enables 8.3 name creation for all volumes on the system.Yes
1Disables 8.3 name creation for all volumes on the system.Yes
2Sets 8.3 name creation on a per volume basis.No, the volume flag decides
3Disables 8.3 name creation for all volumes except the system volume.No, the system volume differs

Applying those four rules to the two kinds of volume a server has gives eight cases. Six of them are settled by the registry value alone. The two that are not are the two that look settled.

default   volume   behaviour      decided by
----------------------------------------------------
0         system   creating       default
0         data     creating       default
1         system   not creating   default
1         data     not creating   default
2         system   unknown        volume flag
2         data     unknown        volume flag
3         system   creating       default
3         data     not creating   default

rows where the registry value alone answers it : 6 of 8
rows that require reading the per-volume flag   : 2 of 8

The practical reading of the table is that two of the four values describe a machine and two describe a policy. 0 and 1 are statements of fact about every volume. 2 is a delegation, and 3 is a rule with an exception built into it. Only the first two can be audited from one reading.

Value 3 splits one machine in two: At 3 the same registry value produces two different behaviours on the same machine, and the system volume is the one still creating short names. A check that samples one data volume and concludes the server is clean has sampled the wrong volume.

Boundary 3: strip skips anything over 260 characters, and says nothing

One sentence on the reference page decides which files strip will walk past: the short name is not removed for any file where the directory path combined with the file name contains more than 260 characters.

That threshold sits one character away from the other documented 260 in Windows, and comparing the two is where it gets interesting. The path length limit page defines MAX_PATH as 260 characters and describes a local path as drive letter, colon, backslash, name components separated by backslashes, and a terminating null character. Its own worked example is a drive letter followed by a 256 character path string and the null.

prefix (drive, colon, backslash)           3
name components                            256
visible characters in the path             259
plus the terminating null                  260

longest path under MAX_PATH, visible chars : 259
strip starts skipping above                : 260
gap, in characters                         : 1

len 258   creatable without \\?\ : yes  strip removes its short name : yes
len 259   creatable without \\?\ : yes  strip removes its short name : yes
len 260   creatable without \\?\ : no   strip removes its short name : yes
len 261   creatable without \\?\ : no   strip removes its short name : no
len 275   creatable without \\?\ : no   strip removes its short name : no
What the arithmetic says: The longest path an ordinary Win32 call can produce is 259 visible characters, because the 260 includes the terminating null. strip only starts skipping above 260. So on a volume where every file arrived through an ordinary API, there is nothing for the rule to skip.

Which raises the question of when it does bite. A real tree answers it. The one below was built on disk: three departments, three years, three record types, five documents each, with the kind of long document names that accumulate on a records share.

files created on disk          : 135
longest path below the share   : 132 characters

root length  skipped    short names removed
----------------------------------------------
14           0          135
60           0          135
82           0          135
127          0          135
128          6          129
160          81         54
200          120        15

shortest share root that makes strip skip ANY file  : 128 characters
shortest share root that makes strip skip EVERY file: 205 characters
longest path the Win32 limit allows at all          : 259 characters

Nothing is skipped until the share root alone is 128 characters long. A share root of 128 characters is not something anybody designs. It is what a tree looks like after it has been moved: into an archive folder, under a legal hold folder, under a folder named after the server it came from.

Running the same 135 files under exactly that kind of root, and separating the two documented rules rather than assuming they agree:

share root                      : 130 characters
files                           : 135
longest path in the tree        : 263

paths longer than 259, the longest a plain Win32 call can create : 12
paths longer than 260, the point at which strip skips a file     : 12
files in the one character band between the two rules            : 0
The files it skips are the ones something else put there: In this tree the two rules select the same twelve files. Those twelve are longer than any plain Win32 call can produce, which means a long path aware tool wrote them: a copy with the extended prefix, a clone, an installer. strip reports the files it processed. It does not report the ones it decided not to.

The remedy follows from the arithmetic rather than from anything strip offers. There is no switch that makes it reach further. The only lever is the path, and the measurement says exactly how much of it has to go.

root shortened by 0   -> 130 characters : 12 still skipped
root shortened by 1   -> 129 characters : 12 still skipped
root shortened by 2   -> 128 characters : 6 still skipped
root shortened by 3   -> 127 characters : 0 still skipped

Three characters off a 130 character root, and a tree that was twelve files short of clean is clean. The jump from six to zero between 128 and 127 is the same threshold seen from the other side: 127 is the longest root at which none of these 135 files crosses 260.

One question the documentation does not answer: The rule says “the directorypath combined with the file name”. It does not say whether that is the path you typed or the path the volume resolves it to. If you reach the same tree through a shorter spelling, does the count change? Nothing published says. The test takes a minute on your own server and the test mode changes nothing:
rem reach the same files through a much shorter path
subst X: "D:\Shares\Departments\Archive\Retained until 2031 under legal hold"

rem the same test-mode run, from the short spelling
fsutil 8dot3name strip /t /s "X:\Migrated from OLDFS01 during the 2026 file server consolidation"

subst X: /d

If the two test-mode runs report the same files, the rule counts the canonical path and a shorter spelling buys nothing. If they differ, it counts what you typed, and subst is a workaround rather than a curiosity. Either answer is worth knowing before a migration rather than after one.

The band exists even though this tree does not use it: A path of exactly 260 characters is above the Win32 limit and still below the skip threshold, so it would be stripped. No file in this fixture landed on that length, so the measured band is zero rather than the arithmetic being wrong.

Boundary 4: disabling creation removes nothing

fsutil 8dot3name set writes a policy about files that do not exist yet. fsutil 8dot3name strip edits files that already do. Neither does the other’s job, and the reference page never puts the two in a sentence together.

CommandActs onEffect on the other half
fsutil 8dot3name setFiles created from now onNone. Every existing short name stays.
fsutil 8dot3name stripFiles that exist now, in one directory treeNone. The volume keeps creating new short names.
A half finished job looks finished: Run strip on its own and a scan of the tree comes back clean, while the volume quietly generates a short name for every file written after it. Run set on its own and the count stops growing while every name already there survives.

This is why the Quick answer puts set before strip. The fsutil behavior table does not put a restart requirement on this row, unlike fourteen of its seventeen, so there is no window to work around: set it, then strip, and the tree stays clean.


Boundary 5: the page says two different things about /f

/f is documented as making the operation remove the short names “even if there are registry keys that point to files using the 8dot3 file name”. That sentence only carries meaning if a registry key would otherwise stop the removal. On that row, strip without /f is a protection and /f turns it off.

The strip row in the same table says the opposite. It describes the command as removing the short names for all files in the directory, and then as listing, but not modifying, the registry keys that point at the files whose names were permanently removed. On that reading nothing was ever stopped and /f has nothing to override.

The rowWhat it says happens to a file a registry key points atWhat that makes /f
The strip rowThe name is removed and the key is listed.Redundant
The /f rowThe name is removed only because /f was given.Load bearing

Both readings cannot be true, and the page gives no way to tell which one describes the build on your server. What both rows do agree on is the part that matters: neither form modifies the keys. Whichever reading is correct, running strip leaves the registry exactly as it found it.

The difference is testable, and test mode makes the test free. Run the same tree twice and compare what each reports, on a tree where scan already found at least one key.

rem the same tree, the same test mode, one flag apart
fsutil 8dot3name strip /t /s /v D:\Shares\Apps
fsutil 8dot3name strip /t /s /v /f D:\Shares\Apps

If the two runs name the same files, the /f row is describing something that does not happen. If the second run names more, /f is doing exactly what its own row claims, and every one of the extra files is one an installer may still be looking for.

What breaking looks like: Microsoft’s warning on this is unusually direct: permanently removing short names without modifying the registry keys that point at them may lead to unexpected application failures, including the inability to uninstall an application. The documented symptom is not that the software stops working; it is that it cannot be removed.

The honest use for /f is a tree where scan is reporting keys that belong to software long since uninstalled. Reading the scan output is what turns that from a guess into a decision, and it is the only part of this section that does not depend on which row of the reference page is right.


What the reference page does not say

Four things are missing or broken on the fsutil 8dot3name page, and one of them changes how you script around it.

  • No output, anywhere. The Examples section lists commands and stops. There is no sample of what query prints, what scan reports, or what a strip run looks like. Anything you find elsewhere claiming to be the documented output is not.
  • The strip syntax line is broken. Its /l option is written with a full stop where the closing angle bracket belongs, so the placeholder never ends. The scan line on the same page is fine.
  • The default log file name does not render. The parameter table gives it with a stray pair of asterisks trailing the extension, which is a formatting error rather than part of the name.
  • Nothing about restarts. The page never mentions whether the setting takes effect immediately. The answer is on the fsutil behavior page instead, and only by omission: its table gives fourteen of seventeen parameters an explicit restart requirement and disable8dot3 is one of the three left out.
The page is the freshest of its family: The fsutil 8dot3name reference carries a 2022 revision date while fsutil behavior, fsutil file, fsutil volume and fsutil fsinfo are all still stamped October 2017. The gaps above are in the most recently maintained page of the set.

Hidden gems

  • A short name can be set by hand. fsutil file setshortname is documented on the fsutil file page and takes a name of your choosing, so a short name is not necessarily the one NTFS generated. That matters when an application needs a specific one back.
  • /v is what puts the log on screen. It is documented as displaying everything written to the log file on the command line as well, and on a large tree that is the difference between watching a run and waiting for one.
  • The 260 rule counts the path, not the name. The same file is strippable in one location and not in another. Moving a tree can change the answer without touching a single file.
  • Extended characters have their own switch. fsutil behavior set allowextchar controls whether characters from the extended set can appear in generated short names, and unlike disable8dot3 it does require a restart.
  • strip /t overlaps with scan but is not the same check. The documentation describes /t as a way to discover which registry keys point at short names, which is what scan is for. The difference is that strip /t performs every operation except the removal itself, so it also surfaces whatever would have stopped the removal.

Where this matters

  • File servers with very large directories. The fsutil behavior page states the cost directly: with creation enabled, NTFS writes a second entry for every long name, and creating files in a directory means looking up the short names already in it.
  • Migrations and consolidations. Nesting a share under an archive path is exactly the change that pushes files past the threshold in Boundary 3, and it happens after the cleanup was signed off.
  • Scripts that delete by wildcard. The asterisk matches short names, so a pattern that looks specific is not. This is the failure mode that costs data rather than time.
  • Older line of business software. Anything that recorded a short path when it was installed is the reason fsutil 8dot3name scan /s exists. It is free to run and it changes nothing.
  • Monitoring and compliance checks. A check that reads the registry value alone is wrong on every machine set to 2, per the table above.
  • Anything that was restored rather than installed. A volume restored from a backup taken on a server with a different default carries its own per volume flag with it, so the restored volume can behave differently from every other volume on its new host.

Tips and limitations

  • Every subcommand needs an elevated prompt. fsutil says so on its own page.
  • There is no undo and no confirmation prompt. strip acts immediately unless /t is present.
  • strip is per directory tree. set is per volume or machine wide. Neither has a form that covers the other’s scope.
  • Because no output is documented, script around the log file and the exit code rather than around the text. Text you have not seen documented can change between builds.
  • The documentation describes the per volume form as setting the volume’s own on-disk 8dot3name properties rather than a registry value, which is why reg query cannot see it and why a volume moved to another server arrives with its flag intact and meets a different machine wide default there.
  • The setting is documented in terms of FAT and NTFS volumes. Confirm the file system with fsutil fsinfo volumeinfo before assuming any of this applies.

Official documentation



Five cheat sheets, one PDF

Subnet masks, PowerShell, Linux commands, HTTP status codes and the ESXi command line - one page each, free to keep. Leave an address and it arrives in a minute.