<p>I want to include a batch file rename functionality in my application. A user can type a destination filename pattern and (after replacing some wildcards in the pattern) I need to check if it's going to be a legal filename under Windows. I've tried to use regular expression like <code>[a-zA-Z0-9_]+</code> but it doesn't include many national-specific characters from various languages (e.g. umlauts and so on). What is the best way to do such a check?</p>

[{'answer_id': 62787, 'author': 'ConroyP', 'author_id': 2287, 'author_profile': 'https://Stackoverflow.com/users/2287', 'pm_score': 3, 'selected': False, 'text': '<p>Rather than explicitly include all possible characters, you could do a regex to check for the presence of illegal characters, and report an error then. Ideally your application should name the files exactly as the user wishes, and only cry foul if it stumbles across an error.</p>\n'}, {'answer_id': 62797, 'author': 'Mark Biek', 'author_id': 305, 'author_profile': 'https://Stackoverflow.com/users/305', 'pm_score': 2, 'selected': False, 'text': '<p>From <a href="http://msdn.microsoft.com/en-us/library/aa365247.aspx" rel="nofollow noreferrer">MSDN</a>, here\'s a list of characters that aren\'t allowed:</p>\n<blockquote>\n<p>Use almost any character in the current code page for a name, including Unicode characters and characters in the extended character set (128–255), except for the following:</p>\n<ul>\n<li>The following reserved characters are not allowed:\n&lt; &gt; : &quot; / \\ | ? *</li>\n<li>Characters whose integer representations are in the range from zero through 31 are not allowed.</li>\n<li>Any other character that the target file system does not allow.</li>\n</ul>\n</blockquote>\n'}, {'answer_id': 62805, 'author': 'Eugene Katz', 'author_id': 1533, 'author_profile': 'https://Stackoverflow.com/users/1533', 'pm_score': 8, 'selected': True, 'text': '<p>You can get a list of invalid characters from <a href="http://msdn.microsoft.com/en-us/library/system.io.path.getinvalidpathchars.aspx" rel="noreferrer"><code>Path.GetInvalidPathChars</code></a> and <a href="http://msdn.microsoft.com/en-us/library/system.io.path.getinvalidfilenamechars.aspx" rel="noreferrer"><code>GetInvalidFileNameChars</code></a>.</p>\n\n<p><strong>UPD:</strong> See <a href="https://stackoverflow.com/questions/62771/how-check-if-given-string-is-legal-allowed-file-name-under-windows#62855">Steve Cooper\'s suggestion</a> on how to use these in a regular expression.</p>\n\n<p><strong>UPD2:</strong> Note that according to the Remarks section in MSDN "The array returned from this method is not guaranteed to contain the complete set of characters that are invalid in file and directory names." <a href="https://stackoverflow.com/questions/62771/how-check-if-given-string-is-legal-allowed-file-name-under-windows/62888#62888">The answer provided by sixlettervaliables</a> goes into more details.</p>\n'}, {'answer_id': 62828, 'author': 'Justin Poliey', 'author_id': 6967, 'author_profile': 'https://Stackoverflow.com/users/6967', 'pm_score': 0, 'selected': False, 'text': '<p>Windows filenames are pretty unrestrictive, so really it might not even be <em>that</em> much of an issue. The characters that are disallowed by Windows are:</p>\n\n<pre><code>\\ / : * ? " &lt; &gt; |\n</code></pre>\n\n<p>You could easily write an expression to check if those characters are present. A better solution though would be to try and name the files as the user wants, and alert them when a filename doesn\'t stick.</p>\n'}, {'answer_id': 62831, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 3, 'selected': False, 'text': '<p>Also CON, PRN, AUX, NUL, COM# and a few others are never legal filenames in any directory with any extension.</p>\n'}, {'answer_id': 62841, 'author': 'Martin Faartoft', 'author_id': 7147, 'author_profile': 'https://Stackoverflow.com/users/7147', 'pm_score': 3, 'selected': False, 'text': '<p>Microsoft Windows: Windows kernel forbids the use of characters in range 1-31 (i.e., 0x01-0x1F) and characters " * : &lt; > ? \\ |. Although NTFS allows each path component (directory or filename) to be 255 characters long and paths up to about 32767 characters long, the Windows kernel only supports paths up to 259 characters long. Additionally, Windows forbids the use of the MS-DOS device names AUX, CLOCK$, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, CON, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9, NUL and PRN, as well as these names with any extension (for example, AUX.txt), except when using Long UNC paths (ex. \\.\\C:\\nul.txt or \\?\\D:\\aux\\con). (In fact, CLOCK$ may be used if an extension is provided.) These restrictions only apply to Windows - Linux, for example, allows use of " * : &lt; > ? \\ | even in NTFS.</p>\n\n<p>Source: <a href="http://en.wikipedia.org/wiki/Filename" rel="noreferrer">http://en.wikipedia.org/wiki/Filename</a></p>\n'}, {'answer_id': 62855, 'author': 'Steve Cooper', 'author_id': 6722, 'author_profile': 'https://Stackoverflow.com/users/6722', 'pm_score': 6, 'selected': False, 'text': '<p>For <strong>.Net Frameworks prior to 3.5</strong> this should work:</p>\n\n<p>Regular expression matching should get you some of the way. Here\'s a snippet using the <code>System.IO.Path.InvalidPathChars</code> constant;</p>\n\n<pre><code>bool IsValidFilename(string testName)\n{\n    Regex containsABadCharacter = new Regex("[" \n          + Regex.Escape(System.IO.Path.InvalidPathChars) + "]");\n    if (containsABadCharacter.IsMatch(testName)) { return false; };\n\n    // other checks for UNC, drive-path format, etc\n\n    return true;\n}\n</code></pre>\n\n<p>For <strong>.Net Frameworks after 3.0</strong> this should work:</p>\n\n<p><a href="http://msdn.microsoft.com/en-us/library/system.io.path.getinvalidpathchars(v=vs.90).aspx" rel="noreferrer">http://msdn.microsoft.com/en-us/library/system.io.path.getinvalidpathchars(v=vs.90).aspx</a></p>\n\n<p>Regular expression matching should get you some of the way. Here\'s a snippet using the <code>System.IO.Path.GetInvalidPathChars()</code> constant;</p>\n\n<pre><code>bool IsValidFilename(string testName)\n{\n    Regex containsABadCharacter = new Regex("["\n          + Regex.Escape(new string(System.IO.Path.GetInvalidPathChars())) + "]");\n    if (containsABadCharacter.IsMatch(testName)) { return false; };\n\n    // other checks for UNC, drive-path format, etc\n\n    return true;\n}\n</code></pre>\n\n<p>Once you know that, you should also check for different formats, eg <code>c:\\my\\drive</code> and <code>\\\\server\\share\\dir\\file.ext</code></p>\n'}, {'answer_id': 62862, 'author': 'kfh', 'author_id': 6597, 'author_profile': 'https://Stackoverflow.com/users/6597', 'pm_score': 3, 'selected': False, 'text': "<p>The question is are you trying to determine if a path name is a legal windows path, or if it's legal <strong>on the system where the code is running.</strong>?  I think the latter is more important, so personally, I'd probably decompose the full path and try to use _mkdir to create the directory the file belongs in, then try to create the file.</p>\n\n<p>This way you know not only if the path contains only valid windows characters, but if it actually represents a path that can be written by this process.</p>\n"}, {'answer_id': 62888, 'author': 'user7116', 'author_id': 7116, 'author_profile': 'https://Stackoverflow.com/users/7116', 'pm_score': 7, 'selected': False, 'text': '<p>From <a href="http://msdn.microsoft.com/en-us/library/aa365247.aspx" rel="noreferrer" title="Naming a File or Directory">MSDN\'s "Naming a File or Directory,"</a> here are the general conventions for what a legal file name is under Windows:</p>\n\n<p>You may use any character in the current code page (Unicode/ANSI above 127), except:</p>\n\n<ul>\n<li><code>&lt;</code> <code>&gt;</code> <code>:</code> <code>"</code> <code>/</code> <code>\\</code> <code>|</code> <code>?</code> <code>*</code></li>\n<li>Characters whose integer representations are 0-31 (less than ASCII space)</li>\n<li>Any other character that the target file system does not allow (say, trailing periods or spaces)</li>\n<li>Any of the DOS names: CON, PRN, AUX, NUL, COM0, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT0, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9 (and avoid AUX.txt, etc)</li>\n<li>The file name is all periods</li>\n</ul>\n\n<p>Some optional things to check:</p>\n\n<ul>\n<li>File paths (including the file name) may not have more than 260 characters (that don\'t use the <code>\\?\\</code> prefix)</li>\n<li>Unicode file paths (including the file name) with more than 32,000 characters when using <code>\\?\\</code> (note that prefix may expand directory components and cause it to overflow the 32,000 limit)</li>\n</ul>\n'}, {'answer_id': 63129, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 5, 'selected': False, 'text': '<p>Try to use it, and trap for the error. The allowed set may change across file systems, or across different versions of Windows. In other words, if you want know if Windows likes the name, hand it the name and let it tell you.</p>\n'}, {'answer_id': 63235, 'author': 'Scott Dorman', 'author_id': 1559, 'author_profile': 'https://Stackoverflow.com/users/1559', 'pm_score': 5, 'selected': False, 'text': '<p>This is what I use:</p>\n\n<pre><code>    public static bool IsValidFileName(this string expression, bool platformIndependent)\n    {\n        string sPattern = @"^(?!^(PRN|AUX|CLOCK\\$|NUL|CON|COM\\d|LPT\\d|\\..*)(\\..+)?$)[^\\x00-\\x1f\\\\?*:\\"";|/]+$";\n        if (platformIndependent)\n        {\n           sPattern = @"^(([a-zA-Z]:|\\\\)\\\\)?(((\\.)|(\\.\\.)|([^\\\\/:\\*\\?""\\|&lt;&gt;\\. ](([^\\\\/:\\*\\?""\\|&lt;&gt;\\. ])|([^\\\\/:\\*\\?""\\|&lt;&gt;]*[^\\\\/:\\*\\?""\\|&lt;&gt;\\. ]))?))\\\\)*[^\\\\/:\\*\\?""\\|&lt;&gt;\\. ](([^\\\\/:\\*\\?""\\|&lt;&gt;\\. ])|([^\\\\/:\\*\\?""\\|&lt;&gt;]*[^\\\\/:\\*\\?""\\|&lt;&gt;\\. ]))?$";\n        }\n        return (Regex.IsMatch(expression, sPattern, RegexOptions.CultureInvariant));\n    }\n</code></pre>\n\n<p>The first pattern creates a regular expression containing the invalid/illegal file names and characters for Windows platforms only. The second one does the same but ensures that the name is legal for any platform.</p>\n'}, {'answer_id': 64807, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 2, 'selected': False, 'text': "<p>Regular expressions are overkill for this situation.  You can use the <code>String.IndexOfAny()</code> method in combination with <code>Path.GetInvalidPathChars()</code> and <code>Path.GetInvalidFileNameChars()</code>.</p>\n\n<p>Also note that both <code>Path.GetInvalidXXX()</code> methods clone an internal array and return the clone.  So if you're going to be doing this a lot (thousands and thousands of times) you can cache a copy of the invalid chars array for reuse.</p>\n"}, {'answer_id': 101706, 'author': 'Jon Schneider', 'author_id': 12484, 'author_profile': 'https://Stackoverflow.com/users/12484', 'pm_score': 4, 'selected': False, 'text': '<p>One corner case to keep in mind, which surprised me when I first found out about it: Windows allows leading space characters in file names!  For example, the following are all legal, and distinct, file names on Windows (minus the quotes):</p>\n\n<pre><code>"file.txt"\n" file.txt"\n"  file.txt"\n</code></pre>\n\n<p>One takeaway from this: Use caution when writing code that trims leading/trailing whitespace from a filename string.</p>\n'}, {'answer_id': 3425681, 'author': 'Steve Cooper', 'author_id': 6722, 'author_profile': 'https://Stackoverflow.com/users/6722', 'pm_score': 5, 'selected': False, 'text': '<p>This class cleans filenames and paths; use it like </p>\n\n<pre><code>var myCleanPath = PathSanitizer.SanitizeFilename(myBadPath, \' \');\n</code></pre>\n\n<p>Here\'s the code;</p>\n\n<pre><code>/// &lt;summary&gt;\n/// Cleans paths of invalid characters.\n/// &lt;/summary&gt;\npublic static class PathSanitizer\n{\n    /// &lt;summary&gt;\n    /// The set of invalid filename characters, kept sorted for fast binary search\n    /// &lt;/summary&gt;\n    private readonly static char[] invalidFilenameChars;\n    /// &lt;summary&gt;\n    /// The set of invalid path characters, kept sorted for fast binary search\n    /// &lt;/summary&gt;\n    private readonly static char[] invalidPathChars;\n\n    static PathSanitizer()\n    {\n        // set up the two arrays -- sorted once for speed.\n        invalidFilenameChars = System.IO.Path.GetInvalidFileNameChars();\n        invalidPathChars = System.IO.Path.GetInvalidPathChars();\n        Array.Sort(invalidFilenameChars);\n        Array.Sort(invalidPathChars);\n\n    }\n\n    /// &lt;summary&gt;\n    /// Cleans a filename of invalid characters\n    /// &lt;/summary&gt;\n    /// &lt;param name="input"&gt;the string to clean&lt;/param&gt;\n    /// &lt;param name="errorChar"&gt;the character which replaces bad characters&lt;/param&gt;\n    /// &lt;returns&gt;&lt;/returns&gt;\n    public static string SanitizeFilename(string input, char errorChar)\n    {\n        return Sanitize(input, invalidFilenameChars, errorChar);\n    }\n\n    /// &lt;summary&gt;\n    /// Cleans a path of invalid characters\n    /// &lt;/summary&gt;\n    /// &lt;param name="input"&gt;the string to clean&lt;/param&gt;\n    /// &lt;param name="errorChar"&gt;the character which replaces bad characters&lt;/param&gt;\n    /// &lt;returns&gt;&lt;/returns&gt;\n    public static string SanitizePath(string input, char errorChar)\n    {\n        return Sanitize(input, invalidPathChars, errorChar);\n    }\n\n    /// &lt;summary&gt;\n    /// Cleans a string of invalid characters.\n    /// &lt;/summary&gt;\n    /// &lt;param name="input"&gt;&lt;/param&gt;\n    /// &lt;param name="invalidChars"&gt;&lt;/param&gt;\n    /// &lt;param name="errorChar"&gt;&lt;/param&gt;\n    /// &lt;returns&gt;&lt;/returns&gt;\n    private static string Sanitize(string input, char[] invalidChars, char errorChar)\n    {\n        // null always sanitizes to null\n        if (input == null) { return null; }\n        StringBuilder result = new StringBuilder();\n        foreach (var characterToTest in input)\n        {\n            // we binary search for the character in the invalid set. This should be lightning fast.\n            if (Array.BinarySearch(invalidChars, characterToTest) &gt;= 0)\n            {\n                // we found the character in the array of \n                result.Append(errorChar);\n            }\n            else\n            {\n                // the character was not found in invalid, so it is valid.\n                result.Append(characterToTest);\n            }\n        }\n\n        // we\'re done.\n        return result.ToString();\n    }\n\n}\n</code></pre>\n'}, {'answer_id': 3551347, 'author': 'Dominik Weber', 'author_id': 428708, 'author_profile': 'https://Stackoverflow.com/users/428708', 'pm_score': 2, 'selected': False, 'text': '<p>Also the destination file system is important.</p>\n\n<p>Under NTFS, some files can not be created in specific directories.\nE.G. $Boot in root </p>\n'}, {'answer_id': 8931637, 'author': 'Joe', 'author_id': 13087, 'author_profile': 'https://Stackoverflow.com/users/13087', 'pm_score': 2, 'selected': False, 'text': '<p>To complement the other answers, here are a couple of additional edge cases that you might want to consider.</p>\n\n<ul>\n<li><p>Excel can have problems if you save a workbook in a file whose name contains the \'[\' or \']\' characters.  See <a href="http://support.microsoft.com/kb/215205" rel="nofollow">http://support.microsoft.com/kb/215205</a> for details.</p></li>\n<li><p>Sharepoint has a whole additional set of restrictions.  See <a href="http://support.microsoft.com/kb/905231" rel="nofollow">http://support.microsoft.com/kb/905231</a> for details.</p></li>\n</ul>\n'}, {'answer_id': 14105459, 'author': 'JerKimball', 'author_id': 48692, 'author_profile': 'https://Stackoverflow.com/users/48692', 'pm_score': 2, 'selected': False, 'text': '<p>This is an already answered question, but just for the sake of "Other options", here\'s a non-ideal one:</p>\n\n<p>(non-ideal because using Exceptions as flow control is a "Bad Thing", generally)</p>\n\n<pre><code>public static bool IsLegalFilename(string name)\n{\n    try \n    {\n        var fileInfo = new FileInfo(name);\n        return true;\n    }\n    catch\n    {\n        return false;\n    }\n}\n</code></pre>\n'}, {'answer_id': 15072694, 'author': 'JoelFan', 'author_id': 16012, 'author_profile': 'https://Stackoverflow.com/users/16012', 'pm_score': 3, 'selected': False, 'text': '<p>I use this to get rid of invalid characters in filenames without throwing exceptions:</p>\n\n<pre><code>private static readonly Regex InvalidFileRegex = new Regex(\n    string.Format("[{0}]", Regex.Escape(@"&lt;&gt;:""/\\|?*")));\n\npublic static string SanitizeFileName(string fileName)\n{\n    return InvalidFileRegex.Replace(fileName, string.Empty);\n}\n</code></pre>\n'}, {'answer_id': 41563828, 'author': 'Tony Sun', 'author_id': 6633541, 'author_profile': 'https://Stackoverflow.com/users/6633541', 'pm_score': 0, 'selected': False, 'text': '<p>I suggest just use the Path.GetFullPath()</p>\n\n<pre><code>string tagetFileFullNameToBeChecked;\ntry\n{\n  Path.GetFullPath(tagetFileFullNameToBeChecked)\n}\ncatch(AugumentException ex)\n{\n  // invalid chars found\n}\n</code></pre>\n'}, {'answer_id': 42589487, 'author': 'tmt', 'author_id': 1475183, 'author_profile': 'https://Stackoverflow.com/users/1475183', 'pm_score': 3, 'selected': False, 'text': "<p>Simplifying the Eugene Katz's answer:</p>\n\n<pre><code>bool IsFileNameCorrect(string fileName){\n    return !fileName.Any(f=&gt;Path.GetInvalidFileNameChars().Contains(f))\n}\n</code></pre>\n\n<p>Or</p>\n\n<pre><code>bool IsFileNameCorrect(string fileName){\n    return fileName.All(f=&gt;!Path.GetInvalidFileNameChars().Contains(f))\n}\n</code></pre>\n"}, {'answer_id': 42777899, 'author': 'Brent', 'author_id': 1022710, 'author_profile': 'https://Stackoverflow.com/users/1022710', 'pm_score': 1, 'selected': False, 'text': '<p>many of these answers will not work if the filename is too long &amp; running on a pre Windows 10 environment. Similarly, have a think about what you want to do with periods - allowing leading or trailing is technically valid, but can create problems if you do not want the file to be difficult to see or delete respectively.</p>\n\n<p>This is a validation attribute I created to check for a valid filename. </p>\n\n<pre><code>public class ValidFileNameAttribute : ValidationAttribute\n{\n    public ValidFileNameAttribute()\n    {\n        RequireExtension = true;\n        ErrorMessage = "{0} is an Invalid Filename";\n        MaxLength = 255; //superseeded in modern windows environments\n    }\n    public override bool IsValid(object value)\n    {\n        //http://stackoverflow.com/questions/422090/in-c-sharp-check-that-filename-is-possibly-valid-not-that-it-exists\n        var fileName = (string)value;\n        if (string.IsNullOrEmpty(fileName)) { return true;  }\n        if (fileName.IndexOfAny(Path.GetInvalidFileNameChars()) &gt; -1 ||\n            (!AllowHidden &amp;&amp; fileName[0] == \'.\') ||\n            fileName[fileName.Length - 1]== \'.\' ||\n            fileName.Length &gt; MaxLength)\n        {\n            return false;\n        }\n        string extension = Path.GetExtension(fileName);\n        return (!RequireExtension || extension != string.Empty)\n            &amp;&amp; (ExtensionList==null || ExtensionList.Contains(extension));\n    }\n    private const string _sepChar = ",";\n    private IEnumerable&lt;string&gt; ExtensionList { get; set; }\n    public bool AllowHidden { get; set; }\n    public bool RequireExtension { get; set; }\n    public int MaxLength { get; set; }\n    public string AllowedExtensions {\n        get { return string.Join(_sepChar, ExtensionList); } \n        set {\n            if (string.IsNullOrEmpty(value))\n            { ExtensionList = null; }\n            else {\n                ExtensionList = value.Split(new char[] { _sepChar[0] })\n                    .Select(s =&gt; s[0] == \'.\' ? s : (\'.\' + s))\n                    .ToList();\n            }\n    } }\n\n    public override bool RequiresValidationContext =&gt; false;\n}\n</code></pre>\n\n<p>and the tests</p>\n\n<pre><code>[TestMethod]\npublic void TestFilenameAttribute()\n{\n    var rxa = new ValidFileNameAttribute();\n    Assert.IsFalse(rxa.IsValid("pptx."));\n    Assert.IsFalse(rxa.IsValid("pp.tx."));\n    Assert.IsFalse(rxa.IsValid("."));\n    Assert.IsFalse(rxa.IsValid(".pp.tx"));\n    Assert.IsFalse(rxa.IsValid(".pptx"));\n    Assert.IsFalse(rxa.IsValid("pptx"));\n    Assert.IsFalse(rxa.IsValid("a/abc.pptx"));\n    Assert.IsFalse(rxa.IsValid("a\\\\abc.pptx"));\n    Assert.IsFalse(rxa.IsValid("c:abc.pptx"));\n    Assert.IsFalse(rxa.IsValid("c&lt;abc.pptx"));\n    Assert.IsTrue(rxa.IsValid("abc.pptx"));\n    rxa = new ValidFileNameAttribute { AllowedExtensions = ".pptx" };\n    Assert.IsFalse(rxa.IsValid("abc.docx"));\n    Assert.IsTrue(rxa.IsValid("abc.pptx"));\n}\n</code></pre>\n'}, {'answer_id': 45887757, 'author': 'Nick Albrecht', 'author_id': 466224, 'author_profile': 'https://Stackoverflow.com/users/466224', 'pm_score': 1, 'selected': False, 'text': '<p>If you\'re only trying to check if a string holding your file name/path has any invalid characters, the fastest method I\'ve found is to use <code>Split()</code> to break up the file name into an array of parts wherever there\'s an invalid character. If the result is only an array of 1, there are no invalid characters. :-)</p>\n\n<pre><code>var nameToTest = "Best file name \\"ever\\".txt";\nbool isInvalidName = nameToTest.Split(System.IO.Path.GetInvalidFileNameChars()).Length &gt; 1;\n\nvar pathToTest = "C:\\\\My Folder &lt;secrets&gt;\\\\";\nbool isInvalidPath = pathToTest.Split(System.IO.Path.GetInvalidPathChars()).Length &gt; 1;\n</code></pre>\n\n<p>I tried running this and other methods mentioned above on a file/path name 1,000,000 times in LinqPad.</p>\n\n<p>Using <code>Split()</code> is only ~850ms.</p>\n\n<p>Using <code>Regex("[" + Regex.Escape(new string(System.IO.Path.GetInvalidPathChars())) + "]")</code> is around 6 seconds.</p>\n\n<p>The more complicated regular expressions fair MUCH worse, as do some of the other options, like using the various methods on the <code>Path</code> class to get file name and let their internal validation do the job (most likely due to the overhead of exception handling).</p>\n\n<p>Granted it\'s not very often you need to validation 1 million file names, so a single iteration is fine for most of these methods anyway. But it\'s still pretty efficient and effective if you\'re only looking for invalid characters.</p>\n'}, {'answer_id': 46503080, 'author': 'Maxence', 'author_id': 200443, 'author_profile': 'https://Stackoverflow.com/users/200443', 'pm_score': 0, 'selected': False, 'text': '<p>My attempt:</p>\n\n<pre><code>using System.IO;\n\nstatic class PathUtils\n{\n  public static string IsValidFullPath([NotNull] string fullPath)\n  {\n    if (string.IsNullOrWhiteSpace(fullPath))\n      return "Path is null, empty or white space.";\n\n    bool pathContainsInvalidChars = fullPath.IndexOfAny(Path.GetInvalidPathChars()) != -1;\n    if (pathContainsInvalidChars)\n      return "Path contains invalid characters.";\n\n    string fileName = Path.GetFileName(fullPath);\n    if (fileName == "")\n      return "Path must contain a file name.";\n\n    bool fileNameContainsInvalidChars = fileName.IndexOfAny(Path.GetInvalidFileNameChars()) != -1;\n    if (fileNameContainsInvalidChars)\n      return "File name contains invalid characters.";\n\n    if (!Path.IsPathRooted(fullPath))\n      return "The path must be absolute.";\n\n    return "";\n  }\n}\n</code></pre>\n\n<p>This is not perfect because <code>Path.GetInvalidPathChars</code> does not return the complete set of characters that are invalid in file and directory names and of course there\'s plenty more subtleties.</p>\n\n<p>So I use this method as a complement:</p>\n\n<pre><code>public static bool TestIfFileCanBeCreated([NotNull] string fullPath)\n{\n  if (string.IsNullOrWhiteSpace(fullPath))\n    throw new ArgumentException("Value cannot be null or whitespace.", "fullPath");\n\n  string directoryName = Path.GetDirectoryName(fullPath);\n  if (directoryName != null) Directory.CreateDirectory(directoryName);\n  try\n  {\n    using (new FileStream(fullPath, FileMode.CreateNew)) { }\n    File.Delete(fullPath);\n    return true;\n  }\n  catch (IOException)\n  {\n    return false;\n  }\n}\n</code></pre>\n\n<p>It tries to create the file and return false if there is an exception. Of course, I need to create the file but I think it\'s the safest way to do that. Please also note that I am not deleting directories that have been created.</p>\n\n<p>You can also use the first method to do basic validation, and then handle carefully the exceptions when the path is used.</p>\n'}, {'answer_id': 46517818, 'author': 'KenR', 'author_id': 8705832, 'author_profile': 'https://Stackoverflow.com/users/8705832', 'pm_score': 1, 'selected': False, 'text': '<p>I got this idea from someone. - don\'t know who. Let the OS do the heavy lifting.</p>\n\n<pre><code>public bool IsPathFileNameGood(string fname)\n{\n    bool rc = Constants.Fail;\n    try\n    {\n        this._stream = new StreamWriter(fname, true);\n        rc = Constants.Pass;\n    }\n    catch (Exception ex)\n    {\n        MessageBox.Show(ex.Message, "Problem opening file");\n        rc = Constants.Fail;\n    }\n    return rc;\n}\n</code></pre>\n'}, {'answer_id': 49301029, 'author': 'Vlad', 'author_id': 276994, 'author_profile': 'https://Stackoverflow.com/users/276994', 'pm_score': 0, 'selected': False, 'text': '<p>This check</p>\n\n<pre><code>static bool IsValidFileName(string name)\n{\n    return\n        !string.IsNullOrWhiteSpace(name) &amp;&amp;\n        name.IndexOfAny(Path.GetInvalidFileNameChars()) &lt; 0 &amp;&amp;\n        !Path.GetFullPath(name).StartsWith(@"\\\\.\\");\n}\n</code></pre>\n\n<p>filters out names with invalid chars (<code>&lt;&gt;:"/\\|?*</code> and ASCII 0-31), as well as reserved DOS devices (<code>CON</code>, <code>NUL</code>, <code>COMx</code>). It allows leading spaces and all-dot-names, consistent with <code>Path.GetFullPath</code>. (Creating file with leading spaces succeeds on my system).</p>\n\n<hr>\n\n<p>Used .NET Framework 4.7.1, tested on Windows 7.</p>\n'}, {'answer_id': 53576616, 'author': 'Zananok', 'author_id': 1612470, 'author_profile': 'https://Stackoverflow.com/users/1612470', 'pm_score': -1, 'selected': False, 'text': '<p>One liner for verifying illigal chars in the string:</p>\n\n<pre><code>public static bool IsValidFilename(string testName) =&gt; !Regex.IsMatch(testName, "[" + Regex.Escape(new string(System.IO.Path.InvalidPathChars)) + "]");\n</code></pre>\n'}, {'answer_id': 57612552, 'author': 'Igor Levicki', 'author_id': 1778190, 'author_profile': 'https://Stackoverflow.com/users/1778190', 'pm_score': -1, 'selected': False, 'text': '<p>In my opinion, the only proper answer to this question is to try to use the path and let the OS and filesystem validate it. Otherwise you are just reimplementing (and probably poorly) all the validation rules that the OS and filesystem already use and if those rules are changed in the future you will have to change your code to match them.</p>\n'}]
['https://Stackoverflow.com/questions/62771', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/7162/']