<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Fsutil on inetshell</title><link>https://inet.sh/en/tags/fsutil/</link><description>Recent content in Fsutil on inetshell</description><generator>Hugo</generator><language>en</language><lastBuildDate>Fri, 25 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://inet.sh/en/tags/fsutil/index.xml" rel="self" type="application/rss+xml"/><item><title>Windows: paths longer than 260 characters (LongPathsEnabled) and why it is sometimes not enough</title><link>https://inet.sh/en/posts/windows/windows-long-paths-longpathsenabled/</link><pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/en/posts/windows/windows-long-paths-longpathsenabled/</guid><description>How to lift the 260-character MAX_PATH limit on Windows 10/11 and Server with the LongPathsEnabled registry value or the &amp;#39;Enable Win32 long paths&amp;#39; policy, which programs honor it (PowerShell 7, .NET, Git with core.longpaths) and which do not (cmd, old apps), and the \\?\ prefix as plan B. Bonus: fsutil file createnew to make test files of an exact size.</description><content:encoded><![CDATA[<h2 id="tldr">TL;DR</h2>
<p>PowerShell as administrator:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">New-ItemProperty</span> <span class="n">-Path</span> <span class="s2">&#34;HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem&#34;</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">  <span class="n">-Name</span> <span class="s2">&#34;LongPathsEnabled&#34;</span> <span class="n">-Value</span> <span class="mf">1</span> <span class="n">-PropertyType</span> <span class="n">DWORD</span> <span class="n">-Force</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Reboot (or at least restart the affected programs). Through Group Policy, the same under <strong>Computer Configuration → Administrative Templates → System → Filesystem → Enable Win32 long paths</strong>.</p>
<p>With that, programs that <strong>declare themselves compatible</strong> stop failing on paths over 260 characters. The ones that do not stay the same: for those, the <code>\\?\</code> prefix, <code>subst</code>, or <code>robocopy</code>.</p>
<h2 id="the-problem">The problem</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters.
</span></span><span class="line"><span class="cl">error: unable to create file ...: Filename too long          # git
</span></span><span class="line"><span class="cl">System.IO.PathTooLongException                              # .NET
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>MAX_PATH</code> is 260 characters including the drive letter and the trailing <code>NUL</code>. It is easy to hit with <code>node_modules</code>, git clones with long names, backups that nest folders, or a sync that brings a deep structure from another system.</p>
<h2 id="what-the-value-does">What the value does</h2>
<p>Since Windows 10 1607 (and Server 2016), many Win32 file functions (<code>CreateFileW</code>, <code>CopyFileW</code>, <code>MoveFileW</code>, <code>FindFirstFileW</code>, <code>CreateDirectoryW</code>…) accept paths up to about 32,767 characters <strong>if two conditions hold</strong>:</p>
<ol>
<li><code>LongPathsEnabled = 1</code> in the registry (or the policy).</li>
<li>The program declares <code>longPathAware</code> in its manifest.</li>
</ol>
<p>Windows reads the value once per process, on the first call to those functions. Hence the reboot: processes that were already running (Explorer, services) keep the old value.</p>
<table>
  <thead>
      <tr>
          <th>Program</th>
          <th>Honors long paths with the value on?</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>PowerShell 7</td>
          <td>Yes</td>
      </tr>
      <tr>
          <td>Windows PowerShell 5.1</td>
          <td>Partially; depends on the cmdlet</td>
      </tr>
      <tr>
          <td>.NET (Core) and modern apps</td>
          <td>Yes</td>
      </tr>
      <tr>
          <td>Git for Windows</td>
          <td>Yes, with <code>git config --system core.longpaths true</code></td>
      </tr>
      <tr>
          <td><code>robocopy</code>, 7-Zip</td>
          <td>Yes (they use <code>\\?\</code> on their own, value or not)</td>
      </tr>
      <tr>
          <td><code>cmd.exe</code> (<code>dir</code>, <code>copy</code>, <code>del</code>)</td>
          <td>No</td>
      </tr>
      <tr>
          <td>File Explorer</td>
          <td>Partial; still trips when copying or deleting</td>
      </tr>
      <tr>
          <td>Old applications</td>
          <td>No, and there is no way to force them</td>
      </tr>
  </tbody>
</table>
<p>Check the value:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Get-ItemProperty</span> <span class="s2">&#34;HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem&#34;</span> <span class="n">-Name</span> <span class="n">LongPathsEnabled</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Quick test in PowerShell 7:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nv">$p</span> <span class="p">=</span> <span class="s2">&#34;C:\t\&#34;</span> <span class="p">+</span> <span class="p">(</span><span class="s2">&#34;a&#34;</span> <span class="p">*</span> <span class="mf">200</span><span class="p">)</span> <span class="p">+</span> <span class="s2">&#34;\&#34;</span> <span class="p">+</span> <span class="p">(</span><span class="s2">&#34;b&#34;</span> <span class="p">*</span> <span class="mf">100</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">New-Item</span> <span class="n">-ItemType</span> <span class="n">Directory</span> <span class="n">-Path</span> <span class="nv">$p</span> <span class="n">-Force</span> <span class="p">|</span> <span class="nb">Out-Null</span>
</span></span><span class="line"><span class="cl"><span class="nb">Get-ChildItem</span> <span class="s2">&#34;C:\t&#34;</span> <span class="n">-Recurse</span> <span class="p">|</span> <span class="nb">Measure-Object</span>
</span></span><span class="line"><span class="cl"><span class="nb">Remove-Item</span> <span class="s2">&#34;C:\t&#34;</span> <span class="n">-Recurse</span> <span class="n">-Force</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="plan-b-when-the-program-will-not-cooperate">Plan B when the program will not cooperate</h2>
<ul>
<li>
<p><strong>The <code>\\?\</code> prefix</strong>: tells Windows to pass the path as is, without the limit. Works on any version with no registry change, but only with absolute paths and no <code>.</code>/<code>..</code>. For UNC: <code>\\?\UNC\server\share\...</code>.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl"><span class="k">dir</span> \\?\C:\projects\very\deep
</span></span><span class="line"><span class="cl"><span class="k">rd</span> /s /q \\?\C:\projects\very\deep\node_modules
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>Shorten the path</strong>: <code>subst X: C:\projects\very\deep</code> creates a drive that starts from zero; <code>net use</code> does the same with UNC paths.</p>
</li>
<li>
<p><strong>Delete what nobody can delete</strong>: <code>robocopy C:\empty C:\impossible\path /MIR</code> with an empty folder leaves the target empty and then it can be removed.</p>
</li>
<li>
<p><strong>Git</strong>: <code>core.longpaths true</code> and, on Windows, clone near the root (<code>C:\src\repo</code>) instead of inside <code>Documents</code>.</p>
</li>
</ul>
<h2 id="traps">Traps</h2>
<ul>
<li><strong>The value is not a global switch.</strong> It is a permission each program has to claim; enabling it breaks nothing, but it does not fix programs that do not ask for it either.</li>
<li><strong>Reboot.</strong> Without it, Explorer and services keep the cached value.</li>
<li><strong>Component names</strong>: each folder or file is still limited to 255 characters; what grows is the total.</li>
<li><strong>Relative paths</strong> are always limited to 260, value or not.</li>
<li><strong>Backwards compatibility</strong>: a file created on a long path may not open from an old program on the same machine. If you share folders with legacy software, keep paths short.</li>
</ul>
<h2 id="bonus-test-files-of-an-exact-size">Bonus: test files of an exact size</h2>
<p>To test transfers, quotas, or space without hunting for a big file:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl">fsutil file createnew C:\temp\dummy-1G.bin 1073741824
</span></span><span class="line"><span class="cl">fsutil file createnew C:\temp\dummy-100M.bin 104857600
</span></span></code></pre></td></tr></table>
</div>
</div><p>It instantly creates a file of the given size in bytes without writing data (it reads as zeros). The upside is that it is instant even for 50 GB; the downside is that it compresses to nothing, so it is useless for measuring compression or deduplication performance.</p>
<p>Reference: <a href="https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation">Maximum Path Length Limitation</a> on Microsoft Learn.</p>
]]></content:encoded></item></channel></rss>