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
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
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}
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.
/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.
| Switch | What it does | When to leave it off |
|---|---|---|
/t | Test mode. Everything except the removal. | Only on the second run, once the test output has been read. |
/s | Apply to the subdirectories as well. | When you genuinely mean one directory. |
/v | Echo everything written to the log to the console too. | In a scheduled job, where the log file is the record. |
/l | Write to a log file you name. | Never, in practice. See the note below. |
/f | Remove the names even where registry keys point at them. | Almost always. See Boundary 5. |
/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
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
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.
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.
| Spelling | What it reads | Sees 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 ... NtfsDisable8dot3NameCreation | The 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.
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.
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 full | What the 1 is | What it changes |
|---|---|---|
fsutil 8dot3name set 1 | A default value | The registry value that applies to every volume |
fsutil 8dot3name set D: 1 | A per volume flag | One volume, and only while the default is 2 |
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.
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.
| Value | Documented meaning | Same answer for every volume |
|---|---|---|
0 | Enables 8.3 name creation for all volumes on the system. | Yes |
1 | Disables 8.3 name creation for all volumes on the system. | Yes |
2 | Sets 8.3 name creation on a per volume basis. | No, the volume flag decides |
3 | Disables 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.
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
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
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.
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.
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.
| Command | Acts on | Effect on the other half |
|---|---|---|
fsutil 8dot3name set | Files created from now on | None. Every existing short name stays. |
fsutil 8dot3name strip | Files that exist now, in one directory tree | None. The volume keeps creating new short names. |
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 row | What it says happens to a file a registry key points at | What that makes /f |
|---|---|---|
The strip row | The name is removed and the key is listed. | Redundant |
The /f row | The 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.
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
queryprints, whatscanreports, or what astriprun looks like. Anything you find elsewhere claiming to be the documented output is not. - The strip syntax line is broken. Its
/loption is written with a full stop where the closing angle bracket belongs, so the placeholder never ends. Thescanline 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 behaviorpage instead, and only by omission: its table gives fourteen of seventeen parameters an explicit restart requirement anddisable8dot3is one of the three left out.
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 setshortnameis documented on thefsutil filepage 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. /vis 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 allowextcharcontrols whether characters from the extended set can appear in generated short names, and unlikedisable8dot3it does require a restart. strip /toverlaps withscanbut is not the same check. The documentation describes/tas a way to discover which registry keys point at short names, which is whatscanis for. The difference is thatstrip /tperforms 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 behaviorpage 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 /sexists. 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.
fsutilsays so on its own page. - There is no undo and no confirmation prompt.
stripacts immediately unless/tis present. stripis per directory tree.setis 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 querycannot 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 volumeinfobefore assuming any of this applies.
Official documentation
- fsutil 8dot3name: Windows Commands | Microsoft Learn
- fsutil behavior: Windows Commands | Microsoft Learn
- fsutil: Windows Commands | Microsoft Learn
- fsutil file: Windows Commands | Microsoft Learn
- dir: Windows Commands | Microsoft Learn
- reg query: Windows Commands | Microsoft Learn
- Naming Files, Paths, and Namespaces | Microsoft Learn
- Maximum Path Length Limitation | Microsoft Learn
Related tools
- ROBOCOPY Command Builder: builds the copy that backs a tree up before a strip, and the one that moves it afterwards.
Related guides
- fsutil in Windows for volume, file and sparse file operations: volumes, sparse files and the rest of the subcommand set.
- The Windows dir command and its switches: where
/xfits, and the switches that show what is really in a directory. - Reading and writing the registry with reg query and reg add: the tool for the value
fsutil 8dot3name setwrites, and the onereg querycannot reach. - The ROBOCOPY command in Windows: moving a tree is what changes the answer in Boundary 3, and this is the tool that moves it.
- What each chkdsk switch does, and when not to run it: what to run when the volume itself, rather than its names, is the problem.
- NTFS links on Windows compared: the other set of names NTFS keeps for a single file.
- Windows Disk and Storage Cheat Sheet: the one page version of
fsutil,chkdskand the rest of the storage commands.
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.