From 07566a2d9a1cc470568bda59bef60b28a9814dbb Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Sun, 4 Oct 2026 21:37:45 +0200 Subject: [PATCH 1/2] PathIo: explain why we can find three-letter extensions and other artifacts on .NET Framework Thanks to Raymond Chen for his wonderful explanation on that topic! --- TruePath.SystemIo/PathIo.cs | 65 ++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/TruePath.SystemIo/PathIo.cs b/TruePath.SystemIo/PathIo.cs index 25b6d0b..71991d3 100644 --- a/TruePath.SystemIo/PathIo.cs +++ b/TruePath.SystemIo/PathIo.cs @@ -3,7 +3,6 @@ // // SPDX-License-Identifier: MIT -using System.Runtime.Versioning; using System.Text; namespace TruePath.SystemIo; @@ -723,8 +722,15 @@ public static class PathIo /// while ?ello.txt matches only hello.txt. /// /// - /// When running on .NET Framework, a three-character extension also matches longer ones, so - /// *.txt additionally matches hello.txtt. + /// When running on .NET Framework on Windows, the pattern is also matched against the short (8.3) name of + /// each file, if it has one. Since a short name keeps at most three characters of the extension, + /// *.htm may also return index.html (whose short name is INDEX~1.HTM), and a pattern + /// such as *1* may match many files with no 1 in their long names, through the ~1 + /// suffix of their short names. Whether a file has a short name depends on the volume settings at the time + /// the file was created, so the results may differ between machines and even between files in the same + /// directory. See + /// Raymond Chen's explanation + /// for details. /// /// /// For the full pattern syntax and its caveats, see @@ -772,8 +778,15 @@ public static class PathIo /// while ?ello.txt matches only hello.txt. /// /// - /// When running on .NET Framework, a three-character extension also matches longer ones, so - /// *.txt additionally matches hello.txtt. + /// When running on .NET Framework on Windows, the pattern is also matched against the short (8.3) name of + /// each file, if it has one. Since a short name keeps at most three characters of the extension, + /// *.htm may also return index.html (whose short name is INDEX~1.HTM), and a pattern + /// such as *1* may match many files with no 1 in their long names, through the ~1 + /// suffix of their short names. Whether a file has a short name depends on the volume settings at the time + /// the file was created, so the results may differ between machines and even between files in the same + /// directory. See + /// Raymond Chen's explanation + /// for details. /// /// /// For the full pattern syntax and its caveats, see @@ -804,6 +817,16 @@ public static class PathIo /// the name, where it may also match none: a? matches both ab and a. /// /// + /// When running on .NET Framework on Windows, the pattern is also matched against the short (8.3) name of + /// each subdirectory, if it has one. So a pattern such as *1* may also return Program Files + /// (whose short name is PROGRA~1), and *.htm may return pages.html (whose short name + /// is PAGES~1.HTM). Whether a subdirectory has a short name depends on the volume settings at the time + /// it was created, so the results may differ between machines and even between subdirectories of the same + /// directory. See + /// Raymond Chen's explanation + /// for details. + /// + /// /// For the full pattern syntax and its caveats, see /// . /// @@ -843,6 +866,16 @@ public static class PathIo /// the name, where it may also match none: a? matches both ab and a. /// /// + /// When running on .NET Framework on Windows, the pattern is also matched against the short (8.3) name of + /// each subdirectory, if it has one. So a pattern such as *1* may also return Program Files + /// (whose short name is PROGRA~1), and *.htm may return pages.html (whose short name + /// is PAGES~1.HTM). Whether a subdirectory has a short name depends on the volume settings at the time + /// it was created, so the results may differ between machines and even between subdirectories of the same + /// directory. See + /// Raymond Chen's explanation + /// for details. + /// + /// /// For the full pattern syntax and its caveats, see /// . /// @@ -876,8 +909,15 @@ public static IEnumerable EnumerateFiles(this AbsolutePath path) /// while ?ello.txt matches only hello.txt. /// /// - /// When running on .NET Framework, a three-character extension also matches longer ones, so - /// *.txt additionally matches hello.txtt. + /// When running on .NET Framework on Windows, the pattern is also matched against the short (8.3) name of + /// each file, if it has one. Since a short name keeps at most three characters of the extension, + /// *.htm may also return index.html (whose short name is INDEX~1.HTM), and a pattern + /// such as *1* may match many files with no 1 in their long names, through the ~1 + /// suffix of their short names. Whether a file has a short name depends on the volume settings at the time + /// the file was created, so the results may differ between machines and even between files in the same + /// directory. See + /// Raymond Chen's explanation + /// for details. /// /// /// For the full pattern syntax and its caveats, see @@ -928,8 +968,15 @@ public static IEnumerable EnumerateFiles(this AbsolutePath path, s /// while ?ello.txt matches only hello.txt. /// /// - /// When running on .NET Framework, a three-character extension also matches longer ones, so - /// *.txt additionally matches hello.txtt. + /// When running on .NET Framework on Windows, the pattern is also matched against the short (8.3) name of + /// each file, if it has one. Since a short name keeps at most three characters of the extension, + /// *.htm may also return index.html (whose short name is INDEX~1.HTM), and a pattern + /// such as *1* may match many files with no 1 in their long names, through the ~1 + /// suffix of their short names. Whether a file has a short name depends on the volume settings at the time + /// the file was created, so the results may differ between machines and even between files in the same + /// directory. See + /// Raymond Chen's explanation + /// for details. /// /// /// For the full pattern syntax and its caveats, see From f876db3c29bbd3bd9ddd9e0f3eef0af8747d6baa Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Sun, 4 Oct 2026 21:40:51 +0200 Subject: [PATCH 2/2] PathIo: fix the using list --- TruePath.SystemIo/PathIo.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/TruePath.SystemIo/PathIo.cs b/TruePath.SystemIo/PathIo.cs index 71991d3..9844a79 100644 --- a/TruePath.SystemIo/PathIo.cs +++ b/TruePath.SystemIo/PathIo.cs @@ -1,9 +1,12 @@ // SPDX-FileCopyrightText: 2025 .NET Foundation and Contributors -// SPDX-FileCopyrightText: 2025 TruePath contributors +// SPDX-FileCopyrightText: 2025-2026 TruePath contributors // // SPDX-License-Identifier: MIT using System.Text; +#if NET8_0_OR_GREATER +using System.Runtime.Versioning; +#endif namespace TruePath.SystemIo;